/* === Work item detail panel ===
   Right-side drawer (same pattern as the jurisdiction panel). Shows the full
   work item; lets permitted users update status, due date/firmness, owner,
   the "where will this be in 2 weeks" note, and mark complete. Every save is
   one event in the append-only log; the panel renders that log as the edit
   history, with status changes called out. Permissions: admins edit anything,
   editors only work items they own, viewers read-only. */

function WorkPanel({ id, onClose }) {
  const w = window.WORK_ITEMS.find((x) => x.id === id);
  const me = window.Store.session();
  const canEdit = !!(me && w && (me.role === "admin" || (me.role === "editor" && w.owner === me.name)));

  const [history, setHistory] = React.useState(null);
  const [err, setErr] = React.useState(null);
  const [busy, setBusy] = React.useState(false);

  const refreshHistory = React.useCallback(() => {
    window.Store.history({ type: "work", id }).then(setHistory).catch(() => setHistory([]));
  }, [id]);
  React.useEffect(() => { setHistory(null); refreshHistory(); }, [id, refreshHistory]);

  React.useEffect(() => {
    const onKey = (e) => { if (e.key === "Escape") onClose(); };
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [onClose]);

  if (!w) return null;

  async function save(patch, prev, note) {
    setBusy(true); setErr(null);
    try {
      await window.Store.commit({ entityType: "work", entityId: id, action: "update", patch, prev, note });
      refreshHistory();
    } catch (e) {
      setErr(String(e.message || e));
    } finally {
      setBusy(false);
    }
  }

  const isCompleted = !!w.completedDate;
  const statusEvents = (history || []).filter((e) => e.patch && ("status" in e.patch || "completedDate" in e.patch));

  return (
    <>
      <div className="scrim is-open" onClick={onClose}></div>
      <aside className="side-panel is-open">
        <div className="side-panel__head">
          <button className="side-panel__close" onClick={onClose} title="Close">
            <svg width="14" height="14" viewBox="0 0 14 14"><path d="M3 3 L11 11 M11 3 L3 11" stroke="currentColor" strokeWidth="1.5" fill="none" strokeLinecap="round" /></svg>
          </button>
          <div className="side-panel__eyebrow">Work item · {w.id} · {w.type}</div>
          <div className="side-panel__title" style={{ fontSize: 19 }}>{w.title}</div>
          <div style={{ marginTop: 10, display: "flex", alignItems: "center", gap: 6, flexWrap: "wrap" }}>
            {w.milestones.map((m) => <ODAChip key={m} id={m} />)}
            {w.oda.map((o) => <Chip key={o} kind="soft">{o}</Chip>)}
            {w.state ? <Chip kind="ghost">{w.state}</Chip> : null}
            {isCompleted
              ? <Chip kind="green">completed {w.completedDate}</Chip>
              : <Chip kind="accent">{w.terminal}</Chip>}
          </div>
          {!canEdit ? (
            <div className="mono faint" style={{ fontSize: 10, marginTop: 8, letterSpacing: ".08em", textTransform: "uppercase" }}>
              {me && me.role === "viewer" ? "view-only account" : `read-only — owned by ${w.owner}`}
            </div>
          ) : null}
        </div>

        {/* Core fields */}
        <div className="side-panel__section">
          <h4>Details</h4>
          <div className="status-block">
            <EditableCell label="Owner" value={w.owner} canEdit={me && me.role === "admin"}
              onSave={(v) => save({ owner: v }, { owner: w.owner })} />
            <div className="status-block__cell">
              <div className="status-block__label">Due · firmness</div>
              <DueEditor w={w} canEdit={canEdit} onSave={save} />
            </div>
          </div>
          {w.stages && w.stages.length ? (
            <div style={{ marginTop: 12 }}>
              <div className="eyebrow" style={{ marginBottom: 6 }}>Stages</div>
              <div className="stage-pipeline">
                {w.stages.map((s, i) => (
                  <div key={i} className={`stage-pipeline__cell ${
                    w.stageStatus[i] === "done" ? "is-done" :
                    w.stageStatus[i] === "current" ? "is-current" :
                    w.stageStatus[i] === "stuck" ? "is-stuck" : ""}`}
                    title={`${s}: ${w.stageStatus[i]}`}></div>
                ))}
              </div>
              <div className="mono faint" style={{ fontSize: 10, marginTop: 4, display: "flex", justifyContent: "space-between" }}>
                <span>{w.stages.map((s, i) => (w.stageStatus[i] === "current" || w.stageStatus[i] === "stuck") ? `↑ ${s}` : null).filter(Boolean).join(" · ")}</span>
                {w.stuckSince ? <span style={{ color: "var(--yellow)" }}>stuck since {w.stuckSince}</span> : null}
              </div>
            </div>
          ) : null}
        </div>

        {/* Status */}
        <div className="side-panel__section">
          <h4>Status</h4>
          <StatusEditor w={w} canEdit={canEdit && !isCompleted} busy={busy} onSave={save} />
          {canEdit ? (
            <div style={{ marginTop: 12 }}>
              {isCompleted ? (
                <button className="btn" disabled={busy}
                  onClick={() => save({ completedDate: null }, { completedDate: w.completedDate }, "reopened")}>
                  Reopen item
                </button>
              ) : (
                <button className="btn btn--primary" disabled={busy}
                  onClick={() => {
                    const d = new Date().toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric" });
                    save({ completedDate: d }, { completedDate: null }, "marked " + w.terminal);
                  }}>
                  Mark {w.terminal} (complete)
                </button>
              )}
            </div>
          ) : null}
          {statusEvents.length ? (
            <div style={{ marginTop: 14 }}>
              <div className="eyebrow" style={{ marginBottom: 6 }}>Status history</div>
              {statusEvents.map((e, i) => (
                <div key={i} style={{ padding: "6px 0", borderTop: "1px solid var(--rule)", fontSize: 12 }}>
                  <div className="row row--between">
                    <span style={{ color: "var(--ink)" }}>
                      {"completedDate" in e.patch
                        ? (e.patch.completedDate ? "completed" : "reopened")
                        : <>{(e.prev && e.prev.status) || "—"} <span className="faint">→</span> <strong>{e.patch.status}</strong></>}
                    </span>
                    <span className="mono faint" style={{ fontSize: 10 }}>{fmtEventTs(e.ts)} · {e.user_name}</span>
                  </div>
                  {e.note ? <div className="muted" style={{ fontSize: 11, fontStyle: "italic", marginTop: 2 }}>{e.note}</div> : null}
                </div>
              ))}
            </div>
          ) : null}
        </div>

        {/* Two-week outlook */}
        <div className="side-panel__section">
          <h4>Where will this be in 2 weeks?</h4>
          <TwoWeekNote w={w} canEdit={canEdit} busy={busy} onSave={save} history={history} />
        </div>

        {/* Full edit history — collapsed by default */}
        <div className="side-panel__section">
          <details>
            <summary style={{ cursor: "pointer", font: "500 11px/1 var(--mono)", letterSpacing: ".14em", color: "var(--ink-mute)", textTransform: "uppercase" }}>
              Edit history {history ? `(${history.length})` : ""}
            </summary>
            <div style={{ marginTop: 10 }}>
              {history === null ? (
                <div className="row" style={{ gap: 8, color: "var(--ink-mute)", fontSize: 12 }}><span className="spinner"></span> Loading…</div>
              ) : history.length === 0 ? (
                <div className="muted" style={{ fontSize: 12 }}>No recorded edits yet — history starts with the first change made in the tracker.</div>
              ) : history.map((e, i) => (
                <div key={i} style={{ padding: "8px 0", borderTop: "1px solid var(--rule)" }}>
                  <div className="row row--between">
                    <span className="mono" style={{ fontSize: 11, color: "var(--ink-2)", fontWeight: 600 }}>{e.user_name || "?"}</span>
                    <span className="mono faint" style={{ fontSize: 10 }}>{fmtEventTs(e.ts)}</span>
                  </div>
                  <div style={{ fontSize: 12, color: "var(--ink-2)", marginTop: 3 }}>
                    {e.action === "create" ? "created this item" :
                     e.action === "delete" ? "deleted this item" :
                     Object.keys(e.patch || {}).map((k) => (
                       <div key={k}>
                         <span className="mono faint" style={{ fontSize: 10, textTransform: "uppercase", letterSpacing: ".08em" }}>{k}</span>{" "}
                         <span className="faint">{fmtVal(e.prev && e.prev[k])}</span> <span className="faint">→</span> {fmtVal(e.patch[k])}
                       </div>
                     ))}
                  </div>
                  {e.note ? <div className="muted" style={{ fontSize: 11, fontStyle: "italic", marginTop: 2 }}>{e.note}</div> : null}
                </div>
              ))}
            </div>
          </details>
        </div>

        {canEdit ? (
          <div className="side-panel__section" style={{ borderBottom: 0 }}>
            <DeleteButton
              label={`Delete ${w.id}`}
              busy={busy}
              onDelete={async () => {
                setBusy(true); setErr(null);
                try {
                  await window.Store.commit({ entityType: "work", entityId: id, action: "delete", prev: { title: w.title }, note: "deleted" });
                  onClose();
                } catch (e) { setErr(String(e.message || e)); setBusy(false); }
              }} />
          </div>
        ) : null}

        {err ? (
          <div style={{ margin: "14px 22px", padding: "8px 12px", borderRadius: 4, background: "var(--red-bg)", color: "var(--red)", fontSize: 12 }}>{err}</div>
        ) : null}
      </aside>
    </>
  );
}

/* Two-step delete: first click arms, second confirms. The event log keeps the
   record of what was deleted, by whom. */
function DeleteButton({ label, busy, onDelete }) {
  const [armed, setArmed] = React.useState(false);
  React.useEffect(() => {
    if (!armed) return;
    const t = setTimeout(() => setArmed(false), 4000);
    return () => clearTimeout(t);
  }, [armed]);
  return armed ? (
    <div className="row" style={{ gap: 8 }}>
      <button className="btn" disabled={busy}
        style={{ background: "var(--red)", color: "white", borderColor: "var(--red)" }}
        onClick={onDelete}>
        Really delete — cannot be undone
      </button>
      <button className="btn btn--ghost" onClick={() => setArmed(false)}>Keep it</button>
    </div>
  ) : (
    <button className="btn btn--ghost" style={{ color: "var(--red)" }} onClick={() => setArmed(true)}>
      {label}
    </button>
  );
}

function fmtVal(v) {
  if (v === null || v === undefined || v === "") return "—";
  if (Array.isArray(v)) return v.length ? v.join(", ") : "—";
  // Structured rationale/note objects ({label, text}) read as their text.
  if (typeof v === "object") return typeof v.text === "string" ? `“${v.text}”` : JSON.stringify(v);
  return String(v);
}

/* Reusable collapsed edit-history block (event log for any entity). */
function EntityHistory({ type, id, label = "Edit history" }) {
  const [history, setHistory] = React.useState(null);
  React.useEffect(() => {
    setHistory(null);
    window.Store.history({ type, id }).then(setHistory).catch(() => setHistory([]));
  }, [type, id]);
  return (
    <details>
      <summary style={{ cursor: "pointer", font: "500 11px/1 var(--mono)", letterSpacing: ".14em", color: "var(--ink-mute)", textTransform: "uppercase" }}>
        {label} {history ? `(${history.length})` : ""}
      </summary>
      <div style={{ marginTop: 10 }}>
        {history === null ? (
          <div className="row" style={{ gap: 8, color: "var(--ink-mute)", fontSize: 12 }}><span className="spinner"></span> Loading…</div>
        ) : history.length === 0 ? (
          <div className="muted" style={{ fontSize: 12 }}>No recorded changes yet.</div>
        ) : history.map((e, i) => (
          <div key={i} style={{ padding: "8px 0", borderTop: "1px solid var(--rule)" }}>
            <div className="row row--between">
              <span className="mono" style={{ fontSize: 11, color: "var(--ink-2)", fontWeight: 600 }}>{e.user_name || "?"}</span>
              <span className="mono faint" style={{ fontSize: 10 }}>{fmtEventTs(e.ts)}</span>
            </div>
            <div style={{ fontSize: 12, color: "var(--ink-2)", marginTop: 3 }}>
              {e.action === "create" ? "created" :
               e.action === "delete" ? "deleted" :
               Object.keys(e.patch || {}).map((k) => (
                 <div key={k}>
                   <span className="mono faint" style={{ fontSize: 10, textTransform: "uppercase", letterSpacing: ".08em" }}>{k}</span>{" "}
                   <span className="faint">{fmtVal(e.prev && e.prev[k])}</span> <span className="faint">→</span> {fmtVal(e.patch[k])}
                 </div>
               ))}
            </div>
            {e.note ? <div className="muted" style={{ fontSize: 11, fontStyle: "italic", marginTop: 2 }}>{e.note}</div> : null}
          </div>
        ))}
      </div>
    </details>
  );
}
Object.assign(window, { EntityHistory });

function fmtEventTs(ts) {
  if (!ts) return "";
  // D1 datetime('now') is "YYYY-MM-DD HH:MM:SS" in UTC; local mode is ISO.
  const iso = ts.includes("T") ? ts : ts.replace(" ", "T") + "Z";
  const d = new Date(iso);
  return isNaN(d) ? ts : d.toLocaleString("en-US", { month: "short", day: "numeric", hour: "numeric", minute: "2-digit" });
}

function EditableCell({ label, value, canEdit, onSave }) {
  const [editing, setEditing] = React.useState(false);
  const [v, setV] = React.useState(value);
  React.useEffect(() => { setV(value); }, [value]);
  return (
    <div className="status-block__cell">
      <div className="status-block__label">{label}</div>
      {editing ? (
        <div className="row" style={{ marginTop: 6, gap: 6 }}>
          <input value={v} onChange={(e) => setV(e.target.value)} autoFocus
            style={{ width: "100%", padding: "5px 8px", borderRadius: 4, border: "1px solid var(--border)", background: "var(--surface-2)", font: "500 13px/1.2 var(--sans)", outline: "none" }} />
          <button className="btn btn--primary" style={{ padding: "4px 9px" }}
            onClick={() => { setEditing(false); if (v !== value) onSave(v); }}>Save</button>
        </div>
      ) : (
        <div className="status-block__value" style={{ fontSize: 15, display: "flex", gap: 8, alignItems: "baseline" }}>
          {value}
          {canEdit ? <button onClick={() => setEditing(true)} className="mono" style={{ fontSize: 10, color: "var(--ink-faint)", letterSpacing: ".08em" }}>EDIT</button> : null}
        </div>
      )}
    </div>
  );
}

function DueEditor({ w, canEdit, onSave }) {
  const [editing, setEditing] = React.useState(false);
  const [due, setDue] = React.useState(w.due);
  const [firm, setFirm] = React.useState(w.firmness || "estimated");
  React.useEffect(() => { setDue(w.due); setFirm(w.firmness || "estimated"); }, [w.due, w.firmness]);
  if (!editing) {
    return (
      <div className="status-block__value" style={{ fontSize: 15, display: "flex", gap: 8, alignItems: "baseline", flexWrap: "wrap" }}>
        <span className="mono" style={{ fontSize: 13 }}>{w.due || "TBD"}</span>
        <Firmness kind={w.firmness || "estimated"} />
        {canEdit ? <button onClick={() => setEditing(true)} className="mono" style={{ fontSize: 10, color: "var(--ink-faint)", letterSpacing: ".08em" }}>EDIT</button> : null}
      </div>
    );
  }
  return (
    <div style={{ marginTop: 6 }}>
      <input value={due} onChange={(e) => setDue(e.target.value)} placeholder="Jun 30, 2026"
        style={{ width: "100%", padding: "5px 8px", borderRadius: 4, border: "1px solid var(--border)", background: "var(--surface-2)", font: "500 12px/1.2 var(--mono)", outline: "none" }} />
      <div className="row" style={{ marginTop: 6, gap: 6 }}>
        <select value={firm} onChange={(e) => setFirm(e.target.value)}
          style={{ flex: 1, padding: "4px 6px", borderRadius: 4, border: "1px solid var(--border)", background: "var(--surface)", font: "500 11px/1.2 var(--mono)" }}>
          <option value="estimated">estimated</option>
          <option value="quoted">quoted</option>
          <option value="locked">locked</option>
        </select>
        <button className="btn btn--primary" style={{ padding: "4px 9px" }}
          onClick={() => {
            setEditing(false);
            const patch = {}, prev = {};
            if (due !== w.due) { patch.due = due; prev.due = w.due; }
            if (firm !== (w.firmness || "estimated")) { patch.firmness = firm; prev.firmness = w.firmness; }
            if (Object.keys(patch).length) onSave(patch, prev);
          }}>Save</button>
      </div>
    </div>
  );
}

function StatusEditor({ w, canEdit, busy, onSave }) {
  const [v, setV] = React.useState(w.status);
  const [note, setNote] = React.useState("");
  React.useEffect(() => { setV(w.status); setNote(""); }, [w.id, w.status]);
  if (!canEdit) {
    return <div className="status-block__value" style={{ fontSize: 15 }}>{w.status}</div>;
  }
  const dirty = v !== w.status;
  return (
    <div>
      <input value={v} onChange={(e) => setV(e.target.value)}
        style={{ width: "100%", padding: "7px 10px", borderRadius: 4, border: "1px solid var(--border)", background: "var(--surface-2)", font: "500 13px/1.2 var(--sans)", outline: "none" }} />
      {dirty ? (
        <div style={{ marginTop: 8 }}>
          <input value={note} onChange={(e) => setNote(e.target.value)} placeholder="Why the change? (optional, shown in history)"
            style={{ width: "100%", padding: "6px 10px", borderRadius: 4, border: "1px solid var(--border)", background: "var(--surface)", fontSize: 12, fontStyle: "italic", outline: "none" }} />
          <div className="row" style={{ marginTop: 8, gap: 8 }}>
            <button className="btn btn--primary" disabled={busy}
              onClick={() => onSave({ status: v }, { status: w.status }, note || null)}>
              Update status
            </button>
            <button className="btn btn--ghost" onClick={() => { setV(w.status); setNote(""); }}>Cancel</button>
          </div>
        </div>
      ) : null}
    </div>
  );
}

function TwoWeekNote({ w, canEdit, busy, onSave, history }) {
  const [v, setV] = React.useState(w.twoWeekNote || "");
  React.useEffect(() => { setV(w.twoWeekNote || ""); }, [w.id, w.twoWeekNote]);
  const last = (history || []).find((e) => e.patch && "twoWeekNote" in e.patch);
  const dirty = v !== (w.twoWeekNote || "");
  return (
    <div>
      {canEdit ? (
        <>
          <textarea value={v} onChange={(e) => setV(e.target.value)} rows={3}
            placeholder="Free text — the answer you'd give John: expected state of this item two weeks from now."
            style={{ width: "100%", padding: "8px 10px", borderRadius: 4, border: "1px solid var(--border)", background: "var(--surface-2)", font: "400 13px/1.5 var(--sans)", outline: "none", resize: "vertical" }} />
          {dirty ? (
            <div className="row" style={{ marginTop: 8, gap: 8 }}>
              <button className="btn btn--primary" disabled={busy}
                onClick={() => onSave({ twoWeekNote: v }, { twoWeekNote: w.twoWeekNote || null })}>
                Save note
              </button>
              <button className="btn btn--ghost" onClick={() => setV(w.twoWeekNote || "")}>Cancel</button>
            </div>
          ) : null}
        </>
      ) : (
        <div style={{ fontSize: 13, color: w.twoWeekNote ? "var(--ink-2)" : "var(--ink-mute)", lineHeight: 1.5 }}>
          {w.twoWeekNote || "No outlook recorded yet."}
        </div>
      )}
      {last ? (
        <div className="mono faint" style={{ fontSize: 10, marginTop: 6 }}>
          last updated {fmtEventTs(last.ts)} by {last.user_name}
        </div>
      ) : null}
    </div>
  );
}

Object.assign(window, { WorkPanel });
