/* ============================================================
   Balance utilities + Employee/CEO dashboard
   ============================================================ */
const { useState, useEffect, useRef } = React;
// Vacation entitlement for the current year, pro-rated by start date.
// Rule: 1/12 of the annual allowance per month employed in VP_DATA.YEAR,
// counting the start month, no rounding (half-days allowed).
function proratedAllowance(person) {
  const base = (person && person.allowance != null) ? person.allowance : VP_DATA.ALLOWANCE;
  if (!person || !person.startDate) return base;
  const year = VP_DATA.YEAR;
  const [sy, sm] = person.startDate.split("-").map(Number);
  if (sy < year) return base;   // started before this year → full entitlement
  if (sy > year) return 0;      // starts in a future year → none yet this year
  const monthsEmployed = 12 - sm + 1;
  return Math.round((base * monthsEmployed) / 12 * 100) / 100;
}
function balanceFor(personId, requests) {
  const person = VP_DATA.byId[personId];
  const allowance = proratedAllowance(person);
  const mine = requests.filter((r) => r.person === personId);
  const counts = (status) => mine
    .filter((r) => r.status === status && VP_DATA.leaveTypes[r.type].countsToBalance)
    .reduce((s, r) => s + workingDays(r), 0);
  const used = counts("approved");
  const pending = counts("pending");
  return { used, pending, remaining: allowance - used, allowance };
}

/* Ring gauge */
function BalanceRing({ used, pending, allowance, size = 168 }) {
  const r = size / 2 - 13;
  const C = 2 * Math.PI * r;
  const usedFrac = Math.min(used / allowance, 1);
  const pendFrac = Math.min((used + pending) / allowance, 1);
  return (
    <div style={{ position: "relative", width: size, height: size }}>
      <svg width={size} height={size} style={{ transform: "rotate(-90deg)" }}>
        <circle cx={size/2} cy={size/2} r={r} stroke="var(--paper-2)" strokeWidth="13" fill="none" />
        {/* pending (lighter) */}
        <circle cx={size/2} cy={size/2} r={r} stroke="var(--st-pending)" strokeWidth="13" fill="none"
          strokeLinecap="round" strokeDasharray={C} strokeDashoffset={C * (1 - pendFrac)}
          opacity="0.32" style={{ transition: "stroke-dashoffset 0.8s cubic-bezier(0.2,0.7,0.2,1)" }} />
        {/* used */}
        <circle cx={size/2} cy={size/2} r={r} stroke="var(--accent)" strokeWidth="13" fill="none"
          strokeLinecap="round" strokeDasharray={C} strokeDashoffset={C * (1 - usedFrac)}
          style={{ transition: "stroke-dashoffset 0.9s cubic-bezier(0.2,0.7,0.2,1)" }} />
      </svg>
      <div style={{ position: "absolute", inset: 0, display: "grid", placeItems: "center", textAlign: "center" }}>
        <div>
          <div style={{ fontFamily: "var(--font-display)", fontSize: 42, fontWeight: 600, letterSpacing: "-0.03em", lineHeight: 1, color: "var(--ink)" }}>
            {allowance - used}
          </div>
          <div style={{ fontSize: 12.5, color: "var(--ink-3)", marginTop: 4, fontWeight: 600 }}>days left</div>
        </div>
      </div>
    </div>
  );
}

function StatChip({ value, label, color }) {
  return (
    <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
      <span style={{ width: 9, height: 9, borderRadius: 3, background: color, flex: "0 0 auto" }} />
      <div>
        <div style={{ fontWeight: 700, fontSize: 16, fontFamily: "var(--font-display)", color: "var(--ink)" }}>{value}</div>
        <div style={{ fontSize: 12, color: "var(--ink-3)" }}>{label}</div>
      </div>
    </div>
  );
}

/* A single request row */
function RequestRow({ req, showPerson, onClick, right }) {
  const [hover, setHover] = useState(false);
  const person = VP_DATA.byId[req.person];
  const rep = req.replacement ? VP_DATA.byId[req.replacement] : null;
  return (
    <div onClick={onClick} onMouseEnter={() => setHover(true)} onMouseLeave={() => setHover(false)}
      style={{
        display: "flex", alignItems: "center", gap: 14, padding: "13px 14px",
        background: hover && onClick ? "var(--surface-2)" : "transparent",
        borderRadius: "var(--r-md)", cursor: onClick ? "pointer" : "default",
        transition: "background 0.14s ease",
      }}>
      {showPerson && <Avatar person={person} size={38} />}
      <div style={{ width: 4, alignSelf: "stretch", borderRadius: 4, background: VP_DATA.leaveTypes[req.type].color, flex: "0 0 auto", minHeight: 34 }} />
      <div style={{ flex: 1, minWidth: 0 }}>
        <div style={{ display: "flex", alignItems: "center", gap: 9, flexWrap: "wrap" }}>
          <span style={{ fontWeight: 600, fontSize: 15, color: "var(--ink)" }}>
            {showPerson ? `${person.first} ${person.last}` : VP_DATA.leaveTypes[req.type].label}
          </span>
          {showPerson && <TypeTag type={req.type} size="sm" />}
        </div>
        <div style={{ fontSize: 13, color: "var(--ink-3)", marginTop: 3, display: "flex", gap: 12, flexWrap: "wrap" }}>
          <span style={{ display: "inline-flex", alignItems: "center", gap: 5 }}>
            <Icon name="calendar" size={13} /> {fmtRange(req.from, req.to)} · {workingDays(req)}{workingDays(req) === 1 ? " day" : " days"}
          </span>
          {rep && <span style={{ display: "inline-flex", alignItems: "center", gap: 5 }}>
            <Icon name="swap" size={13} /> {rep.first} {rep.last}
          </span>}
        </div>
      </div>
      {right || <StatusPill status={req.status} />}
    </div>
  );
}

function SectionTitle({ children, count, action }) {
  return (
    <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: 4 }}>
      <h3 style={{ fontSize: 17, display: "flex", alignItems: "center", gap: 9 }}>
        {children}
        {count != null && <span style={{ fontSize: 13, color: "var(--ink-4)", fontWeight: 600, fontFamily: "var(--font-body)" }}>{count}</span>}
      </h3>
      {action}
    </div>
  );
}

/* Who's out within a window */
function whoIsOut(requests, fromISO_, toISO_) {
  const winA = parseISO(fromISO_), winB = parseISO(toISO_);
  return requests.filter((r) => r.status === "approved")
    .filter((r) => parseISO(r.from) <= winB && parseISO(r.to) >= winA);
}

function Dashboard({ user, requests, onNewRequest, onOpenRequest, onGoto }) {
  const isCeo = user.role === "ceo";
  const narrow = useIsNarrow(820);
  const coCeo = VP_DATA.ceos.find((c) => c.id !== user.id);
  const bal = balanceFor(user.id, requests);
  const mine = requests.filter((r) => r.person === user.id)
    .sort((a, b) => (a.status === "pending" ? -1 : 1) - (b.status === "pending" ? -1 : 1) || parseISO(b.from) - parseISO(a.from));
  const myUpcoming = requests.filter((r) => r.person === user.id && r.status === "approved" && parseISO(r.to) >= parseISO(TODAY))
    .sort((a, b) => parseISO(a.from) - parseISO(b.from));
  const pending = requests.filter((r) => r.status === "pending");

  // this week window
  const weekEnd = toISO(addDays(parseISO(TODAY), 7));
  const outThisWeek = whoIsOut(requests, TODAY, weekEnd).filter((r) => r.person !== user.id);

  return (
    <div className="vp-fade-up" style={{ display: "grid", gap: "var(--gap)" }}>
      {/* Greeting */}
      <div style={{ display: "flex", alignItems: "flex-end", justifyContent: "space-between", gap: 20, flexWrap: "wrap" }}>
        <div>
          <h1 style={{ fontSize: 30 }}>Hi {user.first}</h1>
          <p style={{ color: "var(--ink-3)", margin: "6px 0 0", fontSize: 15 }}>
            {isCeo
              ? (pending.length ? `${pending.length} request${pending.length === 1 ? "" : "s"} to review.` : "No requests to review.")
              : `${bal.remaining} of ${bal.allowance} days left this year.`}
          </p>
        </div>
        <Button size="lg" icon="plus" onClick={onNewRequest}>Request time off</Button>
      </div>

      {(() => {
        const balanceCard = (
          <Card style={{ display: "flex", flexDirection: "column", gap: 18 }}>
            <SectionTitle>{isCeo ? "Your balance" : "Vacation balance"}</SectionTitle>
            <div style={{ display: "flex", alignItems: "center", gap: isCeo ? 18 : 22 }}>
              <BalanceRing used={bal.used} pending={bal.pending} allowance={bal.allowance} size={isCeo ? 118 : 168} />
              <div style={{ display: "grid", gap: isCeo ? 13 : 16 }}>
                <StatChip value={bal.used} label="days used" color="var(--accent)" />
                <StatChip value={bal.pending} label="days pending" color="var(--st-pending)" />
                <StatChip value={bal.allowance} label={bal.allowance !== user.allowance ? "allowance this year" : "annual allowance"} color="var(--paper-2)" />
              </div>
            </div>
          </Card>
        );
        const secondaryCard = isCeo ? (
          <Card style={{ display: "flex", flexDirection: "column" }}>
            <SectionTitle count={pending.length} action={
              <Button size="sm" variant="ghost" iconRight="arrowRight" onClick={() => onGoto("approvals")}>Open inbox</Button>
            }>Awaiting approval</SectionTitle>
            <div style={{ marginTop: 6, display: "grid", gap: 2, marginLeft: -6, marginRight: -6 }}>
              {pending.slice(0, 4).map((r) => (
                <RequestRow key={r.id} req={r} showPerson onClick={() => onOpenRequest(r)} />
              ))}
              {pending.length === 0 && <Empty>Nothing awaiting approval.</Empty>}
            </div>
          </Card>
        ) : (
          <Card style={{ display: "flex", flexDirection: "column" }}>
            <SectionTitle count={myUpcoming.length}>Your upcoming time off</SectionTitle>
            <div style={{ marginTop: 6, display: "grid", gap: 2, marginLeft: -6, marginRight: -6 }}>
              {myUpcoming.slice(0, 3).map((r) => (
                <RequestRow key={r.id} req={r} onClick={() => onOpenRequest(r)} />
              ))}
              {myUpcoming.length === 0 && <Empty>No upcoming time off.</Empty>}
            </div>
          </Card>
        );
        // CEO: lead with the approval queue (their job), balance demoted to the side.
        // Employee: balance leads, upcoming alongside.
        return (
          <div style={{ display: "grid", gridTemplateColumns: narrow ? "1fr" : (isCeo ? "1fr 340px" : "300px 1fr"), gap: "var(--gap)", alignItems: "start" }}>
            {isCeo ? <>{secondaryCard}{balanceCard}</> : <>{balanceCard}{secondaryCard}</>}
          </div>
        );
      })()}

      {/* Bottom row */}
      <div style={{ display: "grid", gridTemplateColumns: narrow ? "1fr" : "1.4fr 1fr", gap: "var(--gap)" }}>
        {/* My requests */}
        <Card style={{ display: "flex", flexDirection: "column" }}>
          <SectionTitle count={mine.length} action={
            <Button size="sm" variant="ghost" iconRight="arrowRight" onClick={() => onGoto("calendar")}>Team calendar</Button>
          }>{isCeo ? "Your requests" : "My requests"}</SectionTitle>
          <div style={{ marginTop: 6, display: "grid", gap: 2, marginLeft: -6, marginRight: -6, maxHeight: 320, overflowY: "auto" }}>
            {mine.map((r) => <RequestRow key={r.id} req={r} onClick={() => onOpenRequest(r)} />)}
            {mine.length === 0 && <Empty>No requests yet.</Empty>}
          </div>
        </Card>

        {/* Who's out this week */}
        <Card style={{ display: "flex", flexDirection: "column" }}>
          <SectionTitle count={outThisWeek.length}>Out this week</SectionTitle>
          <div style={{ marginTop: 10, display: "grid", gap: 12 }}>
            {outThisWeek.slice(0, 6).map((r) => {
              const p = VP_DATA.byId[r.person];
              return (
                <div key={r.id} style={{ display: "flex", alignItems: "center", gap: 12 }}>
                  <Avatar person={p} size={36} />
                  <div style={{ flex: 1, minWidth: 0 }}>
                    <div style={{ fontWeight: 600, fontSize: 14 }}>{p.first} {p.last}</div>
                    <div style={{ fontSize: 12.5, color: "var(--ink-3)" }}>{fmtRange(r.from, r.to)}</div>
                  </div>
                  <TypeTag type={r.type} withLabel={false} size="sm" />
                </div>
              );
            })}
            {outThisWeek.length === 0 && <Empty>Everyone's in this week.</Empty>}
          </div>
        </Card>
      </div>
    </div>
  );
}

function Empty({ children }) {
  return <div style={{ padding: "22px 14px", textAlign: "center", color: "var(--ink-4)", fontSize: 14 }}>{children}</div>;
}

Object.assign(window, { Dashboard, BalanceRing, balanceFor, proratedAllowance, RequestRow, SectionTitle, Empty, whoIsOut, StatChip });
