// Roster — workforce management with interactive AI fills + plan approval.

function Roster() {
  const { state, dispatch } = useApp();
  const hours = Array.from({ length: 24 }, (_, i) => i);
  const view = state.filters.rosterView;
  const roleFilter = state.filters.rosterRole;
  const aiOn = state.filters.rosterAIOn;

  // Role filter counts from live state.
  const roleCounts = React.useMemo(() => {
    const c = { all: 0, RN: 0, EN: 0, PCA: 0, Agency: 0 };
    state.rosterRows.forEach(r => {
      c.all++;
      const role = (r.staff.role || "").toUpperCase();
      if (role === "RN") c.RN++;
      if (role === "EN") c.EN++;
      if (role === "PCA") c.PCA++;
      if (r.staff.agency) c.Agency++;
    });
    return c;
  }, [state.rosterRows]);

  const visibleRows = state.rosterRows.filter(row => {
    if (!aiOn && row.staff.ai) return false;
    if (roleFilter === "all") return true;
    if (roleFilter === "Agency") return !!row.staff.agency;
    return (row.staff.role || "").toUpperCase() === roleFilter;
  });

  function toggleAI() {
    dispatch({ type: "TOGGLE_AI_ROSTER" });
    dispatch({ type: "PUSH_TOAST", toast: { tone: aiOn ? "ok" : "ai", text: aiOn ? "AI suggestions hidden" : "AI re-ran optimisation · 3 suggestions ready" } });
  }

  return (
    <div className="page">
      <div className="page-head">
        <div>
          <div className="eyebrow">Workforce management</div>
          <h1 className="page-title" style={{ marginTop: 4 }}>Banksia ward · Fri 24 Apr 2026</h1>
          <div className="page-sub">NuCo optimised this roster 06:40 this morning. <strong>{state.plans.some(p => p.id === "PL-001") ? "3 changes" : "0 changes"}</strong> suggested · projected saving <strong>$1,240</strong></div>
        </div>
        <div className="hstack" style={{ flexWrap: "wrap" }}>
          <div className="seg">
            <button data-active={!state.rosterWeekMode} onClick={() => dispatch({ type: "SET_ROSTER_WEEK", on: false })}>Day</button>
            <button data-active={state.rosterWeekMode}  onClick={() => dispatch({ type: "SET_ROSTER_WEEK", on: true })}>Week</button>
          </div>
          <div className="seg">
            <button data-active={view === "staff"} onClick={() => dispatch({ type: "SET_FILTER", key: "rosterView", value: "staff" })}>By staff</button>
            <button data-active={view === "role"}  onClick={() => dispatch({ type: "SET_FILTER", key: "rosterView", value: "role" })}>By role</button>
            <button data-active={view === "task"}  onClick={() => dispatch({ type: "SET_FILTER", key: "rosterView", value: "task" })}>By task</button>
            <button data-active={view === "ward"}  onClick={() => dispatch({ type: "SET_FILTER", key: "rosterView", value: "ward" })}>By ward</button>
          </div>
          <Dropdown align="right" trigger={<button className="btn"><Icon name="filter" size={13} /> Filters</button>}>
            {(close) => (
              <>
                <div className="dropdown-label">Ward</div>
                {["Banksia (viewing)","Wattle","Grevillea","Bottlebrush"].map(w => (
                  <DropdownItem key={w} icon="calendar" label={w} onClick={() => { dispatch({ type: "PUSH_TOAST", toast: { tone: "ok", text: `Switched roster view: ${w}` } }); close(); }} />
                ))}
                <div className="dropdown-divider" />
                <DropdownItem icon="x" label="Clear filters" onClick={() => { dispatch({ type: "SET_FILTER", key: "rosterRole", value: "all" }); close(); }} />
              </>
            )}
          </Dropdown>
          <button className="btn sage" onClick={toggleAI}>
            <Icon name="sparkle" size={13} /> {aiOn ? "Clear AI suggestions" : "Run AI optimisation"}
          </button>
        </div>
      </div>

      {/* AI banner — only when plan is available. */}
      {state.plans.some(p => p.id === "PL-001") && aiOn && (
        <div className="card" style={{ background: "var(--sage-wash)", borderColor: "var(--sage)", marginBottom: 18 }}>
          <div className="card-head" style={{ alignItems: "flex-start", flexWrap: "wrap", gap: 12 }}>
            <div style={{ display: "flex", gap: 12, alignItems: "flex-start" }}>
              <div className="ex-ico" data-tone="ai" style={{ width: 28, height: 28 }}><Icon name="sparkle" size={14} /></div>
              <div>
                <div className="card-title" style={{ color: "var(--sage-ink)" }}>NuCo proposes 3 changes to this roster</div>
                <div className="sub" style={{ color: "var(--sage-ink)", marginTop: 4 }}>
                  Maintains 1:7 ratio, meets care-minute target (215 min/res), avoids 2 consecutive double shifts, reduces agency reliance from 2 to 1.
                </div>
                <div className="hstack" style={{ gap: 14, marginTop: 10, fontSize: 11.5, flexWrap: "wrap" }}>
                  <span className="mono"><strong style={{ color: "var(--sage-ink)" }}>−$1,240</strong> labour cost</span>
                  <span className="mono"><strong style={{ color: "var(--sage-ink)" }}>+8 min</strong> care/resident</span>
                  <span className="mono"><strong style={{ color: "var(--sage-ink)" }}>0</strong> compliance risk</span>
                  <span className="mono"><strong style={{ color: "var(--sage-ink)" }}>1</strong> agency → internal swap</span>
                </div>
              </div>
            </div>
            <div className="hstack">
              <button className="btn" onClick={() => dispatch({ type: "COPILOT_MSG", msg: { role: "ai", text: "Here's why I made each change: (1) Siobhán K. is the lowest-cost eligible RN for the Banksia night slot — $412 under agency. (2) Grace W. swap avoids a 2nd consecutive agency pay. (3) Aisha's 8h block absorbs Wattle's 15:00 peak without an overtime penalty." } })}>Explain</button>
              <button className="btn" onClick={() => dispatch({ type: "OPEN_MODAL", modal: { kind: "plan-review", planId: "PL-001" } })}>Compare</button>
              <button className="btn sage" onClick={() => dispatch({ type: "OPEN_MODAL", modal: { kind: "plan-review", planId: "PL-001" } })}>Review & apply</button>
            </div>
          </div>
        </div>
      )}

      {/* Legend & filters */}
      <div className="hstack" style={{ marginBottom: 12, gap: 10, flexWrap: "wrap" }}>
        <div className="kbar">
          {[
            { key: "all",    label: "All roles", count: roleCounts.all },
            { key: "RN",     label: "RN",        count: roleCounts.RN },
            { key: "EN",     label: "EN",        count: roleCounts.EN },
            { key: "PCA",    label: "PCA",       count: roleCounts.PCA },
            { key: "Agency", label: "Agency",    count: roleCounts.Agency },
          ].map(r => (
            <button key={r.key} className="chip" data-active={roleFilter === r.key}
              onClick={() => dispatch({ type: "SET_FILTER", key: "rosterRole", value: r.key })}>
              {r.label} <span className="count">{r.count}</span>
            </button>
          ))}
        </div>
        <div style={{ marginLeft: "auto" }} className="hstack">
          <span className="hstack" style={{ fontSize: 11, gap: 6, flexWrap: "wrap" }}>
            <span style={{ width: 14, height: 10, background: "#E6DFCF", border: "1px solid #D3C9B0" }} /> Day
            <span style={{ width: 14, height: 10, background: "#D9DAD0", border: "1px solid #BEC0B0", marginLeft: 8 }} /> Evening
            <span style={{ width: 14, height: 10, background: "#D4D7DF", border: "1px solid #B4B8C4", marginLeft: 8 }} /> Night
            <span style={{ width: 14, height: 10, background: "repeating-linear-gradient(45deg,#F3E6D0 0 4px,#EEDBB5 4px 8px)", border: "1px solid var(--amber)", marginLeft: 8 }} /> Agency
            <span style={{ width: 14, height: 10, background: "var(--sage-wash)", border: "1px dashed var(--sage)", marginLeft: 8 }} /> NuCo suggestion
          </span>
        </div>
      </div>

      {view === "staff" && (state.rosterWeekMode ? <RosterWeekGrid rows={visibleRows} /> : <RosterStaffGrid rows={visibleRows} hours={hours} />)}
      {view === "role" && <RosterRolePivot rows={visibleRows} />}
      {view === "task" && <RosterTaskPivot rows={visibleRows} />}
      {view === "ward" && <RosterWardPivot rows={visibleRows} />}

      {/* Optimisation insights */}
      <div className="grid" style={{ gridTemplateColumns: "repeat(auto-fit, minmax(260px, 1fr))", marginTop: 20, gap: 16 }}>
        <div className="card">
          <div className="card-head">
            <div>
              <div className="card-title">Ratio adherence</div>
              <div className="card-sub">Mandated 1:7 day · 1:10 evening · 1:15 night</div>
            </div>
            <Badge tone="ok" dot>within target</Badge>
          </div>
          <div className="card-body hstack" style={{ gap: 14 }}>
            <Ring pct={1.0} label="1:7" color="var(--sage)" />
            <div className="vstack" style={{ gap: 4, fontSize: 11.5 }}>
              <div>Day <strong>1:7.0</strong></div>
              <div>Evening <strong>1:9.8</strong></div>
              <div className="hstack" style={{ gap: 6 }}>Night <strong style={{ color: "var(--amber-ink)" }}>1:15.4</strong> <Badge tone="warn" dot>borderline</Badge></div>
            </div>
          </div>
        </div>

        <div className="card">
          <div className="card-head">
            <div>
              <div className="card-title">Why NuCo chose Siobhán</div>
              <div className="card-sub">Night RN fill · Fri 24 Apr 23:00–07:00</div>
            </div>
            <AIChip onClick={() => dispatch({ type: "SET_COPILOT", open: true })}>explain</AIChip>
          </div>
          <div className="card-body vstack" style={{ gap: 8, fontSize: 12 }}>
            {[
              ["AHPRA valid",       "Yes",         "ok"],
              ["Ratio satisfied",   "1:7 → 1:7",   "ok"],
              ["Within award hours","32/38h",      "ok"],
              ["No consecutive nights","Last night 5 days ago", "ok"],
              ["Cost vs agency",    "$412 lower than Medacs", "ok"],
              ["Travel distance",   "7.2 km",      "ok"],
            ].map(([k, v, t], i) => (
              <div key={i} className="hstack" style={{ justifyContent: "space-between", paddingBottom: 4, borderBottom: "1px dashed var(--line)" }}>
                <span className="sub">{k}</span>
                <span className="hstack" style={{ gap: 6 }}>
                  <Badge tone={t} dot>{v}</Badge>
                </span>
              </div>
            ))}
          </div>
        </div>

        <div className="card">
          <div className="card-head">
            <div>
              <div className="card-title">Cost & agency projection</div>
              <div className="card-sub">This week after applying suggestions</div>
            </div>
          </div>
          <div className="card-body">
            <div className="hstack" style={{ justifyContent: "space-between", alignItems: "flex-end", marginBottom: 10 }}>
              <div>
                <div className="serif" style={{ fontSize: 24, fontWeight: 500 }}>$248,900</div>
                <div className="sub">Projected total labour</div>
              </div>
              <Badge tone="ok" dot>−$1,240 vs current</Badge>
            </div>
            <Bars values={[24, 22, 19, 18, 16, 14, 12]} highlightIdx={6} />
            <div className="sub mono" style={{ fontSize: 10.5, marginTop: 4, textAlign: "right" }}>Agency spend (wk −6 → wk 0)</div>
          </div>
        </div>
      </div>

      <ShiftDrawer />
    </div>
  );
}

function RosterStaffGrid({ rows, hours }) {
  const { dispatch } = useApp();
  return (
    <div className="roster-wrap">
      <div className="roster">
        <div className="rh" style={{ position: "sticky", left: 0, zIndex: 3 }}>Staff / Role</div>
        {hours.map(h => (
          <div key={h} className="rh time">{String(h).padStart(2,'0')}</div>
        ))}
        {rows.map((row, ri) => (
          <React.Fragment key={ri}>
            <div className="rname">
              {row.staff.open ? (
                <>
                  <div className="avatar" style={{ background: "transparent", border: "1px dashed var(--amber)", color: "var(--amber-ink)" }}>?</div>
                  <div style={{ minWidth: 0 }}>
                    <div style={{ fontWeight: 500, color: "var(--amber-ink)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{row.staff.name}</div>
                    <div className="person-meta">{row.staff.ward}</div>
                  </div>
                </>
              ) : row.staff.ai ? (
                <>
                  <div className="avatar" style={{ background: "var(--sage-wash)", border: "1px dashed var(--sage)", color: "var(--sage-ink)" }}><Icon name="sparkle" size={11} /></div>
                  <div style={{ minWidth: 0 }}>
                    <div style={{ fontWeight: 500, color: "var(--sage-ink)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{row.staff.name}</div>
                    <div className="person-meta">AI suggestion</div>
                  </div>
                </>
              ) : (
                <>
                  <AvatarInitials name={row.staff.name} tone={row.staff.tone} size={26} />
                  <div style={{ minWidth: 0 }}>
                    <div style={{ fontWeight: 500, fontSize: 12.5, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{row.staff.name}</div>
                    <div className="person-meta">{row.staff.grade || row.staff.role} · {row.staff.hours}h</div>
                  </div>
                </>
              )}
            </div>
            {hours.map(h => {
              const shift = row.shifts.find(s => h >= s.start && (s.wrap ? h < 24 : h < s.end));
              const isStart = shift && shift.start === h;
              return (
                <div key={h} className="rslot">
                  {isStart && (
                    <div className="shift"
                      data-kind={shift.kind}
                      data-blocked={shift.blocked ? "true" : "false"}
                      style={{
                        left: 2, right: 2,
                        width: `calc(${((shift.wrap ? 24 : shift.end) - shift.start)*100}% - 4px)`
                      }}
                      onClick={() => dispatch({ type: "SELECT_SHIFT", shift: { rowIndex: ri, row, shift } })}
                    >
                      {shift.blocked && <Icon name="lock" size={10} />}
                      {shift.kind === "ai" && <Icon name="sparkle" size={10} />}
                      <span style={{ overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{shift.label}</span>
                    </div>
                  )}
                </div>
              );
            })}
          </React.Fragment>
        ))}
      </div>
    </div>
  );
}

function RosterRolePivot({ rows }) {
  const { dispatch } = useApp();
  const byRole = rows.reduce((acc, row) => {
    const role = row.staff.open ? "Open" : row.staff.ai ? "AI suggested" : (row.staff.role || "Other");
    (acc[role] = acc[role] || []).push(row);
    return acc;
  }, {});
  const order = ["RN","EN","PCA","Open","AI suggested","Other"];
  return (
    <div className="vstack" style={{ gap: 12 }}>
      {order.filter(r => byRole[r]).map(role => (
        <div key={role} className="card">
          <div className="card-head">
            <div>
              <div className="card-title">{role}</div>
              <div className="card-sub">{byRole[role].length} · total hours {byRole[role].reduce((a, r) => a + (r.staff.hours || 8), 0)}</div>
            </div>
            <Badge tone={role === "Open" ? "warn" : role === "AI suggested" ? "ai" : "ok"} dot>{role}</Badge>
          </div>
          <div className="card-body vstack" style={{ gap: 8 }}>
            {byRole[role].map((row, i) => (
              <div key={i} className="hstack" style={{ justifyContent: "space-between", padding: "6px 0", borderBottom: "1px dashed var(--line)" }}>
                <div className="hstack" style={{ gap: 10 }}>
                  {row.staff.open ? (
                    <div className="avatar" style={{ background: "transparent", border: "1px dashed var(--amber)", color: "var(--amber-ink)" }}>?</div>
                  ) : row.staff.ai ? (
                    <div className="avatar" style={{ background: "var(--sage-wash)", border: "1px dashed var(--sage)", color: "var(--sage-ink)" }}><Icon name="sparkle" size={11} /></div>
                  ) : <AvatarInitials name={row.staff.name} tone={row.staff.tone} size={26} />}
                  <div>
                    <div style={{ fontWeight: 500, fontSize: 12.5 }}>{row.staff.name}</div>
                    <div className="sub">{row.staff.ward} · {row.shifts.map(s => `${String(s.start).padStart(2,'0')}:00–${String(s.wrap ? 7 : s.end).padStart(2,'0')}:00`).join(", ")}</div>
                  </div>
                </div>
                <button className="btn ghost" onClick={() => dispatch({ type: "SELECT_SHIFT", shift: { rowIndex: rows.indexOf(row), row, shift: row.shifts[0] } })}>
                  Open <Icon name="arrowRight" size={12} />
                </button>
              </div>
            ))}
          </div>
        </div>
      ))}
    </div>
  );
}

function RosterWeekGrid({ rows }) {
  const { dispatch } = useApp();
  const days = ["Mon 20","Tue 21","Wed 22","Thu 23","Fri 24","Sat 25","Sun 26"];
  // Deterministic pseudo pattern: each staff member has shifts on 4–5 days of the week.
  const seedKinds = ["day","evening","night","day","evening","night","day"];
  function shiftFor(row, dayIdx) {
    if (row.staff.open) return dayIdx === 4 ? { kind: "open", label: "RN required" } : null;
    if (row.staff.ai) return dayIdx === 4 ? { kind: "ai", label: "Accept?" } : null;
    const pattern = (row.staff.id || "E-1000").charCodeAt(row.staff.id.length - 1) % 7;
    // 5-day working pattern starting at `pattern`.
    const on = [0,1,2,3,4].map(i => (pattern + i) % 7).includes(dayIdx);
    if (!on) return null;
    const kind = seedKinds[(dayIdx + pattern) % seedKinds.length];
    const label = kind === "day" ? "Day" : kind === "evening" ? "PM" : "Night";
    return { kind, label: `${label} · ${row.staff.role || "—"}` };
  }
  return (
    <div className="roster-wrap">
      <div style={{ display: "grid", gridTemplateColumns: "200px repeat(7, 1fr)", minWidth: 900 }}>
        <div className="rh" style={{ position: "sticky", left: 0, zIndex: 3 }}>Staff / Role</div>
        {days.map(d => <div key={d} className="rh time" style={{ textAlign: "center" }}>{d}</div>)}
        {rows.map((row, ri) => (
          <React.Fragment key={ri}>
            <div className="rname">
              {row.staff.open ? (
                <>
                  <div className="avatar" style={{ background: "transparent", border: "1px dashed var(--amber)", color: "var(--amber-ink)" }}>?</div>
                  <div style={{ minWidth: 0 }}>
                    <div style={{ fontWeight: 500, color: "var(--amber-ink)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{row.staff.name}</div>
                    <div className="person-meta">{row.staff.ward}</div>
                  </div>
                </>
              ) : row.staff.ai ? (
                <>
                  <div className="avatar" style={{ background: "var(--sage-wash)", border: "1px dashed var(--sage)", color: "var(--sage-ink)" }}><Icon name="sparkle" size={11} /></div>
                  <div style={{ minWidth: 0 }}>
                    <div style={{ fontWeight: 500, color: "var(--sage-ink)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{row.staff.name}</div>
                    <div className="person-meta">AI suggestion</div>
                  </div>
                </>
              ) : (
                <>
                  <AvatarInitials name={row.staff.name} tone={row.staff.tone} size={26} />
                  <div style={{ minWidth: 0 }}>
                    <div style={{ fontWeight: 500, fontSize: 12.5, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{row.staff.name}</div>
                    <div className="person-meta">{row.staff.grade || row.staff.role} · {row.staff.hours}h</div>
                  </div>
                </>
              )}
            </div>
            {days.map((_, di) => {
              const s = shiftFor(row, di);
              return (
                <div key={di} className="rslot" style={{ minHeight: 44, padding: 4 }}>
                  {s && (
                    <div className="shift" data-kind={s.kind} style={{ position: "static", width: "100%", overflow: "hidden" }}
                      onClick={() => dispatch({ type: "SELECT_SHIFT", shift: { rowIndex: ri, row, shift: { ...s, start: 7, end: 15, wrap: false } } })}>
                      {s.kind === "ai" && <Icon name="sparkle" size={10} />}
                      <span style={{ overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{s.label}</span>
                    </div>
                  )}
                </div>
              );
            })}
          </React.Fragment>
        ))}
      </div>
    </div>
  );
}

function RosterWardPivot({ rows }) {
  const { state, dispatch } = useApp();
  const wards = ["Banksia", "Wattle", "Grevillea", "Bottlebrush"];
  const ratios = { Banksia: "1:7", Wattle: "1:8", Grevillea: "1:10", Bottlebrush: "1:9" };
  return (
    <div className="grid" style={{ gridTemplateColumns: "repeat(auto-fit, minmax(280px, 1fr))", gap: 16 }}>
      {wards.map(ward => {
        const wardRows = rows.filter(r => r.staff.ward === ward);
        const total = wardRows.length;
        const open = wardRows.filter(r => r.staff.open).length;
        const agency = wardRows.filter(r => r.staff.agency).length;
        const filled = total - open;
        const pct = total ? filled / total : 1;
        return (
          <div key={ward} className="card">
            <div className="card-head">
              <div>
                <div className="card-title">{ward}</div>
                <div className="card-sub">Mandated ratio {ratios[ward]} · {filled}/{total} filled</div>
              </div>
              <Badge tone={open > 0 ? "warn" : "ok"} dot>{open > 0 ? `${open} open` : "Staffed"}</Badge>
            </div>
            <div className="card-body vstack" style={{ gap: 8 }}>
              <div style={{ height: 6, background: "var(--paper-2)", borderRadius: 3 }}>
                <div style={{ width: `${pct*100}%`, height: "100%", background: open > 0 ? "var(--amber)" : "var(--sage)", borderRadius: 3 }} />
              </div>
              <div className="hstack" style={{ gap: 12, fontSize: 11.5, color: "var(--ink-3)" }}>
                <span>Internal <strong style={{ color: "var(--ink)" }}>{total - agency - open}</strong></span>
                <span>Agency <strong style={{ color: "var(--ink)" }}>{agency}</strong></span>
                <span>Open <strong style={{ color: open > 0 ? "var(--amber-ink)" : "var(--ink)" }}>{open}</strong></span>
              </div>
              <div className="divider" style={{ margin: "6px 0" }} />
              {wardRows.map((row, i) => (
                <div key={i} className="hstack"
                  style={{ justifyContent: "space-between", padding: "4px 0", borderBottom: i < wardRows.length - 1 ? "1px dashed var(--line)" : "none", cursor: "pointer" }}
                  onClick={() => dispatch({ type: "SELECT_SHIFT", shift: { rowIndex: state.rosterRows.indexOf(row), row, shift: row.shifts[0] } })}>
                  <div className="hstack" style={{ gap: 8 }}>
                    {row.staff.open ? <div className="avatar" style={{ width: 22, height: 22, background: "transparent", border: "1px dashed var(--amber)", color: "var(--amber-ink)", fontSize: 10 }}>?</div>
                      : row.staff.ai ? <div className="avatar" style={{ width: 22, height: 22, background: "var(--sage-wash)", border: "1px dashed var(--sage)" }}><Icon name="sparkle" size={10} /></div>
                      : <AvatarInitials name={row.staff.name} tone={row.staff.tone} size={22} />}
                    <div>
                      <div style={{ fontSize: 12, fontWeight: 500 }}>{row.staff.name}</div>
                      <div className="sub mono" style={{ fontSize: 10.5 }}>{row.shifts.map(s => `${String(s.start).padStart(2,'0')}–${String(s.wrap ? 7 : s.end).padStart(2,'0')}`).join(",")}</div>
                    </div>
                  </div>
                  <Badge tone={row.staff.status === "block" ? "block" : row.staff.status === "warn" ? "warn" : "ok"} dot>{row.staff.role || "—"}</Badge>
                </div>
              ))}
              {wardRows.length === 0 && <div className="sub">No shifts in this ward for the current filter.</div>}
            </div>
          </div>
        );
      })}
    </div>
  );
}

function RosterTaskPivot({ rows }) {
  const tasks = [
    { name: "Medication rounds",    kind: "day", time: "06:30 · 12:00 · 18:00 · 22:00", assigned: rows.filter(r => r.staff.role === "RN").length, req: 2, tone: "ok" },
    { name: "Personal care",        kind: "day", time: "07:00 · 13:00 · 19:00",         assigned: rows.filter(r => r.staff.role === "PCA").length, req: 3, tone: "ok" },
    { name: "Wound & clinical",     kind: "day", time: "09:00 · 15:00",                 assigned: 1, req: 1, tone: "ok" },
    { name: "Falls rounds (hourly)", kind: "night", time: "22:00 – 06:00",                  assigned: 1, req: 1, tone: "warn" },
    { name: "Clinical handover",    kind: "day", time: "07:00 · 15:00 · 23:00",         assigned: 3, req: 3, tone: "ok" },
  ];
  return (
    <div className="card">
      <div className="card-head">
        <div>
          <div className="card-title">Tasks mapped to shifts</div>
          <div className="card-sub">Live task coverage · care-minute weighted</div>
        </div>
        <Badge tone="ok" dot>All core tasks covered</Badge>
      </div>
      <div className="card-body vstack" style={{ gap: 8 }}>
        {tasks.map((t, i) => (
          <div key={i} className="hstack" style={{ justifyContent: "space-between", padding: "8px 0", borderBottom: i < tasks.length - 1 ? "1px dashed var(--line)" : "none" }}>
            <div>
              <div style={{ fontWeight: 500, fontSize: 12.5 }}>{t.name}</div>
              <div className="sub mono" style={{ fontSize: 11 }}>{t.time}</div>
            </div>
            <div className="hstack" style={{ gap: 10 }}>
              <div className="mono sub" style={{ fontSize: 11 }}>{t.assigned}/{t.req} assigned</div>
              <Badge tone={t.tone} dot>{t.tone === "ok" ? "Covered" : "Review"}</Badge>
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}

function ShiftDrawer() {
  const { state, dispatch } = useApp();
  const sel = state.selected.shift;
  if (!sel) return null;
  const { row, shift, rowIndex } = sel;
  const close = () => dispatch({ type: "SELECT_SHIFT", shift: null });

  // Candidate suggestions for open/ai shifts — filter eligible RNs.
  const candidates = row.staff.open
    ? state.staff.filter(s => s.role === "RN" && s.status === "ok").slice(0, 3)
    : [];

  function accept() {
    if (row.staff.ai) {
      // Accept AI: convert ai row into agency row using "Siobhán K." (pre-modelled).
      const siobhan = state.staff.find(s => s.id === "A-2017") || state.staff[8];
      dispatch({ type: "ASSIGN_SHIFT", rowIndex, newStaff: siobhan, kind: "agency", label: "Night · Agency RN" });
      dispatch({ type: "PUSH_TOAST", toast: { tone: "ok", text: `Shift filled · ${siobhan.name} · Fri Night` } });
    } else if (row.staff.open && candidates[0]) {
      const pick = candidates[0];
      dispatch({ type: "ASSIGN_SHIFT", rowIndex, newStaff: pick, kind: pick.agency ? "agency" : "night", label: `Night · ${pick.role}` });
      dispatch({ type: "PUSH_TOAST", toast: { tone: "ok", text: `Shift filled · ${pick.name} · Fri Night` } });
    }
    close();
  }

  function fillWith(staff) {
    dispatch({ type: "ASSIGN_SHIFT", rowIndex, newStaff: staff, kind: staff.agency ? "agency" : "night", label: `Night · ${staff.role}` });
    dispatch({ type: "PUSH_TOAST", toast: { tone: "ok", text: `Shift filled · ${staff.name} · Fri Night` } });
    close();
  }

  function dismissSuggestion() {
    if (row.staff.ai) {
      dispatch({ type: "REMOVE_ROSTER_ROW", rowIndex });
      dispatch({ type: "PUSH_TOAST", toast: { tone: "ok", text: "Suggestion dismissed" } });
    }
    close();
  }

  return (
    <Drawer open={true} onClose={close}
      title={row.staff.open ? "Fill open shift" : row.staff.ai ? "AI suggestion" : "Shift detail"}
      subtitle={`${shift.label} · ${String(shift.start).padStart(2,'0')}:00 – ${String(shift.wrap ? 7 : shift.end).padStart(2,'0')}:00`}
      width={420}
      footer={
        row.staff.ai ? (<><button className="btn" onClick={dismissSuggestion}>Dismiss</button><button className="btn sage" onClick={accept}><Icon name="check" size={12} /> Accept AI fill</button></>)
        : row.staff.open ? (<><button className="btn" onClick={close}>Close</button><button className="btn sage" onClick={accept}><Icon name="check" size={12} /> Fill with top pick</button></>)
        : (<><button className="btn" onClick={() => { dispatch({ type: "PUSH_TOAST", toast: { tone: "ok", text: `${row.staff.name} marked unavailable for this shift` } }); close(); }}>Mark unavailable</button><button className="btn" onClick={() => dispatch({ type: "PUSH_TOAST", toast: { tone: "ai", text: "Reassignment flow — NuCo drafted 2 candidates." } })}>Reassign</button></>)
      }>
      {!row.staff.open && !row.staff.ai && (
        <div className="vstack" style={{ gap: 10 }}>
          <div className="hstack" style={{ gap: 10 }}>
            <AvatarInitials name={row.staff.name} tone={row.staff.tone} size={42} />
            <div>
              <div style={{ fontWeight: 600, fontSize: 14 }}>{row.staff.name}</div>
              <div className="sub">{row.staff.grade} · {row.staff.ward} · {row.staff.id}</div>
            </div>
          </div>
          {shift.blocked && <Badge tone="block" dot>Blocked — credential expired</Badge>}
          <div className="vstack" style={{ gap: 4, fontSize: 12 }}>
            <div className="hstack" style={{ justifyContent: "space-between" }}><span className="sub">Hours this week</span><span className="mono">{row.staff.hours}h</span></div>
            <div className="hstack" style={{ justifyContent: "space-between" }}><span className="sub">AHPRA</span><span className="mono">{row.staff.ahpra}</span></div>
            <div className="hstack" style={{ justifyContent: "space-between" }}><span className="sub">Role</span><span className="mono">{row.staff.role}</span></div>
          </div>
        </div>
      )}

      {row.staff.ai && (
        <div className="vstack" style={{ gap: 10 }}>
          <div style={{ padding: 12, background: "var(--sage-wash)", border: "1px solid var(--sage)", borderRadius: 8, color: "var(--sage-ink)", fontSize: 12.5 }}>
            <div className="hstack" style={{ gap: 8, marginBottom: 4 }}>
              <Icon name="sparkle" size={13} /><strong>NuCo proposal</strong>
            </div>
            Swap open RN slot for Siobhán K. Same ratio, $412 lower than Medacs agency, no consecutive nights.
          </div>
          <Chain steps={["Eligibility","Ratio","Cost","Approve"]} />
        </div>
      )}

      {row.staff.open && (
        <div className="vstack" style={{ gap: 14 }}>
          <div>
            <div className="eyebrow" style={{ marginBottom: 6 }}>Top internal candidates</div>
            <div className="vstack" style={{ gap: 8 }}>
              {candidates.map(c => (
                <div key={c.id} className="hstack" style={{ justifyContent: "space-between", padding: 10, background: "var(--bone)", border: "1px solid var(--line)", borderRadius: 8 }}>
                  <div className="hstack" style={{ gap: 8 }}>
                    <Gate tone={c.status} />
                    <Person name={c.name} meta={`${c.role} · ${c.hours}h · ${c.ward}`} tone={c.tone} />
                  </div>
                  <button className="btn sage" onClick={() => fillWith(c)}>Fill <Icon name="arrowRight" size={12} /></button>
                </div>
              ))}
              {candidates.length === 0 && <div className="sub">No internal candidates — consider agency below.</div>}
            </div>
          </div>
          <div>
            <div className="hstack" style={{ justifyContent: "space-between", marginBottom: 6 }}>
              <div className="eyebrow">Request from agency</div>
              <span className="sub" style={{ fontSize: 10.5 }}>NuCo brokers the request end-to-end</span>
            </div>
            <div className="vstack" style={{ gap: 6 }}>
              {state.agencies.map(a => (
                <div key={a.id} className="hstack" style={{ justifyContent: "space-between", padding: 10, background: "var(--paper)", border: "1px solid var(--line)", borderRadius: 8 }}>
                  <div style={{ minWidth: 0 }}>
                    <div className="hstack" style={{ gap: 8 }}>
                      <AvatarInitials name={a.name} tone={a.tone} size={22} />
                      <div>
                        <div style={{ fontWeight: 500, fontSize: 12.5 }}>{a.name}</div>
                        <div className="sub" style={{ fontSize: 11 }}>{a.note}</div>
                      </div>
                    </div>
                    <div className="hstack" style={{ gap: 10, marginTop: 6, fontSize: 10.5, color: "var(--ink-3)" }}>
                      <span className="mono">${a.rate.toFixed(2)}/hr</span>
                      <span className="mono">★ {a.rating}</span>
                      <span className="mono">{a.fill}</span>
                    </div>
                  </div>
                  <button className="btn" onClick={() => {
                    dispatch({ type: "PUSH_TOAST", toast: { tone: "ai", text: `Agency request sent · ${a.name}` } });
                    dispatch({ type: "LOG_AUDIT", event: { module: "Roster", action: "Agency request sent", detail: `${a.name} · $${a.rate.toFixed(2)}/hr`, tone: "warn" } });
                  }}>Request<Icon name="arrowRight" size={12} /></button>
                </div>
              ))}
            </div>
          </div>
        </div>
      )}
    </Drawer>
  );
}

Object.assign(window, { Roster });
