/* ============================================================
   Request detail (with approve/decline) + Approvals inbox
   ============================================================ */
const { useState, useEffect, useRef } = React;
function RequestDetail({ req, user, requests, onDecide, onClose }) {
  const [declining, setDeclining] = useState(false);
  const [reason, setReason] = useState("");
  const person = VP_DATA.byId[req.person];
  const rep = req.replacement ? VP_DATA.byId[req.replacement] : null;
  const lt = VP_DATA.leaveTypes[req.type];
  const isCeo = user.role === "ceo";
  const canDecide = isCeo && req.status === "pending";
  const decidedBy = req.decidedBy ? VP_DATA.byId[req.decidedBy] : null;

  // Conflicts: who else is out during this window
  const overlap = whoIsOut(requests, req.from, req.to)
    .filter((r) => r.person !== req.person && r.id !== req.id);

  return (
    <div>
      {/* header strip in type color */}
      <div style={{ height: 6, background: lt.color, borderRadius: "var(--r-xl) var(--r-xl) 0 0" }} />
      <div style={{ padding: "22px 26px", borderBottom: "1px solid var(--line)", display: "flex", justifyContent: "space-between", alignItems: "flex-start", gap: 16 }}>
        <div style={{ display: "flex", gap: 14, alignItems: "center" }}>
          <Avatar person={person} size={48} />
          <div>
            <h2 style={{ fontSize: 21 }}>{person.first} {person.last}</h2>
            <div style={{ color: "var(--ink-3)", fontSize: 13.5 }}>{person.team} · submitted {daysAgo(req.submitted)}</div>
          </div>
        </div>
        <button type="button" onClick={onClose} className="vp-focusable" style={{ ...navBtn, border: "none", background: "var(--paper-2)" }}><Icon name="x" size={18} /></button>
      </div>

      <div style={{ padding: "22px 26px", display: "grid", gap: 18 }}>
        <div style={{ display: "flex", gap: 10, alignItems: "center" }}>
          <TypeTag type={req.type} />
          <StatusPill status={req.status} />
        </div>

        {/* Key facts grid */}
        <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 1, background: "var(--line)", borderRadius: "var(--r-md)", overflow: "hidden", border: "1px solid var(--line)" }}>
          <Fact icon="calendar" label="Period" value={fmtRange(req.from, req.to)} sub={`${workingDays(req)} working ${workingDays(req) === 1 ? "day" : "days"}`} />
          <Fact icon="swap" label="Replacement" value={rep ? `${rep.first} ${rep.last}` : "None"} sub={rep ? rep.team : (lt.needsReplacement ? "—" : "Not required")} avatar={rep} />
        </div>

        {req.note && (
          <div style={{ padding: "13px 15px", background: "var(--surface-2)", borderRadius: "var(--r-md)", border: "1px solid var(--line)" }}>
            <div style={{ fontSize: 11.5, fontWeight: 700, letterSpacing: "0.06em", textTransform: "uppercase", color: "var(--ink-4)", marginBottom: 5 }}>Note</div>
            <div style={{ fontSize: 14.5, color: "var(--ink-2)", lineHeight: 1.5 }}>“{req.note}”</div>
          </div>
        )}

        {/* Overlap warning */}
        {overlap.length > 0 && (
          <div style={{ display: "flex", gap: 11, padding: "12px 14px", background: "var(--st-pending-soft)", borderRadius: "var(--r-md)", color: "var(--st-pending)" }}>
            <Icon name="info" size={18} style={{ flex: "0 0 auto", marginTop: 1 }} />
            <div style={{ fontSize: 13.5, lineHeight: 1.5 }}>
              <strong>{overlap.map((r) => VP_DATA.byId[r.person].first).join(", ")}</strong> {overlap.length === 1 ? "is" : "are"} also off during part of this period.
            </div>
          </div>
        )}

        {/* Decision record */}
        {req.status !== "pending" && decidedBy && (
          <div style={{ fontSize: 13.5, color: "var(--ink-3)", display: "flex", alignItems: "center", gap: 8 }}>
            <Avatar person={decidedBy} size={24} />
            {req.status === "approved" ? "Approved" : "Declined"} by {decidedBy.first} {decidedBy.last} · {fmtDateLong(req.decidedOn)}
          </div>
        )}
        {req.status === "declined" && req.reason && (
          <div style={{ fontSize: 14, color: "var(--st-declined)", background: "var(--st-declined-soft)", padding: "11px 14px", borderRadius: "var(--r-md)" }}>
            “{req.reason}”
          </div>
        )}
      </div>

      {/* Footer actions */}
      {canDecide && (
        <div style={{ padding: "16px 26px", borderTop: "1px solid var(--line)", background: "var(--surface)" }}>
          {!declining ? (
            <div style={{ display: "flex", gap: 10, justifyContent: "flex-end" }}>
              <Button variant="decline" icon="x" onClick={() => setDeclining(true)}>Decline</Button>
              <Button variant="approve" icon="check" onClick={() => onDecide(req.id, "approved", user.id)}>Approve</Button>
            </div>
          ) : (
            <div className="vp-fade" style={{ display: "grid", gap: 10 }}>
              <input autoFocus value={reason} onChange={(e) => setReason(e.target.value)} placeholder="Reason for declining (optional)…"
                className="vp-focusable" style={{ width: "100%", padding: "10px 13px", fontSize: 14, border: "1px solid var(--line-2)", borderRadius: "var(--r-sm)", outline: "none" }} />
              <div style={{ display: "flex", gap: 10, justifyContent: "flex-end" }}>
                <Button variant="ghost" onClick={() => setDeclining(false)}>Back</Button>
                <Button variant="decline" icon="x" onClick={() => onDecide(req.id, "declined", user.id, reason.trim())}>Confirm decline</Button>
              </div>
            </div>
          )}
        </div>
      )}
    </div>
  );
}

function Fact({ icon, label, value, sub, avatar }) {
  return (
    <div style={{ background: "var(--surface)", padding: "14px 16px" }}>
      <div style={{ display: "flex", alignItems: "center", gap: 7, fontSize: 11.5, fontWeight: 700, letterSpacing: "0.06em", textTransform: "uppercase", color: "var(--ink-4)", marginBottom: 7 }}>
        <Icon name={icon} size={14} /> {label}
      </div>
      <div style={{ display: "flex", alignItems: "center", gap: 9 }}>
        {avatar && <Avatar person={avatar} size={28} />}
        <div>
          <div style={{ fontWeight: 600, fontSize: 16, fontFamily: "var(--font-display)", color: "var(--ink)" }}>{value}</div>
          {sub && <div style={{ fontSize: 12.5, color: "var(--ink-3)" }}>{sub}</div>}
        </div>
      </div>
    </div>
  );
}

/* ----- Approvals inbox ----- */
function ApprovalsInbox({ user, requests, onOpenRequest, onDecide, onNewRequest }) {
  const [filter, setFilter] = useState("pending");
  const pending = requests.filter((r) => r.status === "pending").sort((a, b) => parseISO(a.from) - parseISO(b.from));
  const decided = requests.filter((r) => r.status !== "pending").sort((a, b) => parseISO(b.decidedOn || b.submitted) - parseISO(a.decidedOn || a.submitted));
  const list = filter === "pending" ? pending : decided;

  return (
    <div className="vp-fade-up" style={{ display: "grid", gap: "var(--gap)" }}>
      <div style={{ display: "flex", alignItems: "flex-end", justifyContent: "space-between", gap: 20, flexWrap: "wrap" }}>
        <div>
          <h1 style={{ fontSize: 30 }}>Approval inbox</h1>
          <p style={{ color: "var(--ink-3)", margin: "6px 0 0", fontSize: 15 }}>
            {pending.length} request{pending.length === 1 ? "" : "s"} waiting. A decision here also clears it for your co-CEO.
          </p>
        </div>
        <div style={{ display: "inline-flex", background: "var(--paper-2)", borderRadius: "var(--r-pill)", padding: 4 }}>
          {[["pending", "Pending", pending.length], ["decided", "Decided", decided.length]].map(([id, label, n]) => (
            <button key={id} onClick={() => setFilter(id)} className="vp-focusable"
              style={{
                border: "none", cursor: "pointer", padding: "8px 16px", borderRadius: "var(--r-pill)",
                fontWeight: 600, fontSize: 13.5, fontFamily: "var(--font-body)",
                background: filter === id ? "var(--surface)" : "transparent",
                color: filter === id ? "var(--ink)" : "var(--ink-3)",
                boxShadow: filter === id ? "var(--sh-sm)" : "none", transition: "all 0.15s",
              }}>{label} <span style={{ color: "var(--ink-4)" }}>{n}</span></button>
          ))}
        </div>
      </div>

      {filter === "pending" && pending.length > 0 ? (
        <div style={{ display: "grid", gap: 14 }}>
          {pending.map((r) => <ApprovalCard key={r.id} req={r} user={user} requests={requests} onOpenRequest={onOpenRequest} onDecide={onDecide} />)}
        </div>
      ) : filter === "pending" ? (
        <Card style={{ textAlign: "center", padding: "56px 20px" }}>
          <div style={{ width: 56, height: 56, borderRadius: "50%", background: "var(--st-approved-soft)", color: "var(--st-approved)", display: "grid", placeItems: "center", margin: "0 auto 14px" }}>
            <Icon name="check" size={28} stroke={2} />
          </div>
          <h3 style={{ fontSize: 19 }}>Inbox zero</h3>
          <p style={{ color: "var(--ink-3)", fontSize: 14.5, marginTop: 4 }}>No requests are waiting for a decision.</p>
        </Card>
      ) : (
        <Card pad="8px">
          <div style={{ display: "grid", gap: 2 }}>
            {decided.map((r) => <RequestRow key={r.id} req={r} showPerson onClick={() => onOpenRequest(r)} />)}
            {decided.length === 0 && <Empty>No decisions yet.</Empty>}
          </div>
        </Card>
      )}
    </div>
  );
}

/* Rich approval card with inline actions */
function ApprovalCard({ req, user, requests, onOpenRequest, onDecide }) {
  const person = VP_DATA.byId[req.person];
  const rep = req.replacement ? VP_DATA.byId[req.replacement] : null;
  const lt = VP_DATA.leaveTypes[req.type];
  const overlap = whoIsOut(requests, req.from, req.to).filter((r) => r.person !== req.person && r.id !== req.id);
  return (
    <Card pad="0" style={{ overflow: "hidden", display: "flex" }}>
      <div style={{ width: 5, background: lt.color, flex: "0 0 auto" }} />
      <div style={{ flex: 1, padding: "18px 20px", display: "flex", gap: 18, alignItems: "center", flexWrap: "wrap" }}>
        <div style={{ display: "flex", gap: 13, alignItems: "center", minWidth: 220, flex: 1 }}>
          <Avatar person={person} size={46} />
          <div>
            <div style={{ display: "flex", alignItems: "center", gap: 9 }}>
              <span style={{ fontWeight: 600, fontSize: 16 }}>{person.first} {person.last}</span>
              <TypeTag type={req.type} withLabel={false} size="sm" />
            </div>
            <div style={{ fontSize: 13, color: "var(--ink-3)", marginTop: 3, display: "flex", gap: 13, flexWrap: "wrap" }}>
              <span style={{ display: "inline-flex", gap: 5, alignItems: "center" }}><Icon name="calendar" size={13} /> {fmtRange(req.from, req.to)} · {workingDays(req)}{workingDays(req) === 1 ? "d" : "d"}</span>
              {rep && <span style={{ display: "inline-flex", gap: 5, alignItems: "center" }}><Icon name="swap" size={13} /> {rep.first} {rep.last}</span>}
            </div>
          </div>
        </div>
        {overlap.length > 0 && (
          <div title="Overlapping absence" style={{ display: "inline-flex", alignItems: "center", gap: 6, color: "var(--st-pending)", background: "var(--st-pending-soft)", padding: "5px 10px", borderRadius: "var(--r-pill)", fontSize: 12.5, fontWeight: 600 }}>
            <Icon name="info" size={14} /> overlap
          </div>
        )}
        <div style={{ display: "flex", gap: 9, alignItems: "center" }}>
          <Button variant="ghost" size="sm" onClick={() => onOpenRequest(req)}>Details</Button>
          <Button variant="decline" size="sm" icon="x" onClick={() => onDecide(req.id, "declined", user.id)}>Decline</Button>
          <Button variant="approve" size="sm" icon="check" onClick={() => onDecide(req.id, "approved", user.id)}>Approve</Button>
        </div>
      </div>
    </Card>
  );
}

Object.assign(window, { RequestDetail, ApprovalsInbox, ApprovalCard, Fact });
