// Admin triage view: the team's queue of tickets that are ALREADY in Jira.
// Same TicketCard as the customer view (mode=admin), so a ticket has one
// structure everywhere — admins just also see the SEV code, account, reporter,
// SLA state, and the Jira link.
//
// Usable at volume: filter by account / severity / status / component, free-text
// search, and sort — including "most overdue", which is the order you actually
// want to work the queue in.
const { useState: useStateTB, useEffect: useEffectTB, useMemo: useMemoTB } = React;

const SORTS = [
  { key: "sla", label: "Most overdue" },
  { key: "severity", label: "Severity" },
  { key: "newest", label: "Newest" },
  { key: "oldest", label: "Oldest" },
  { key: "account", label: "Account" },
];

function Chip({ on, onClick, children, title }) {
  return (
    <button type="button" className={"fchip" + (on ? " is-on" : "")} onClick={onClick} title={title}>
      {children}
    </button>
  );
}

function TriageBoard({ focusKey }) {
  const [tickets, setTickets] = useStateTB(() => window.NS.tickets.all());
  const [q, setQ] = useStateTB(focusKey || "");
  const [sevs, setSevs] = useStateTB([]);          // empty = all
  const [account, setAccount] = useStateTB("");
  const [component, setComponent] = useStateTB("");
  const [status, setStatus] = useStateTB("open");  // open | all | done
  const [sort, setSort] = useStateTB("sla");
  const [group, setGroup] = useStateTB(true);

  useEffectTB(() => {
    const unsub = window.NS.tickets.subscribe(() => setTickets(window.NS.tickets.all()));
    window.NS.tickets.refresh("").then(() => setTickets(window.NS.tickets.all()));
    return unsub;
  }, []);

  // Only tickets that actually exist in Jira belong on this board — the rest are
  // still in the validation queue.
  const filed = useMemoTB(
    () => tickets.map((t) => window.NS.normalizeTicket(t)).filter((t) => t.stage === "filed"),
    [tickets]);

  const accounts = useMemoTB(() => uniq(filed.map((t) => t.account)), [filed]);
  const components = useMemoTB(() => uniq(filed.map((t) => t.component)), [filed]);

  const rows = useMemoTB(() => {
    const needle = q.trim().toLowerCase();
    let out = filed.filter((t) => {
      if (status === "open" && t.statusCategory === "Done") return false;
      if (status === "done" && t.statusCategory !== "Done") return false;
      if (sevs.length && sevs.indexOf(t.severity) < 0) return false;
      if (account && t.account !== account) return false;
      if (component && t.component !== component) return false;
      if (needle) {
        const hay = [t.key, t.title, t.reporter, t.account, t.component].join(" ").toLowerCase();
        if (hay.indexOf(needle) < 0) return false;
      }
      return true;
    });
    const now = Date.now();
    const bySev = (t) => window.NS.sev(t.severity).rank;
    out.sort((a, b) => {
      switch (sort) {
        case "severity": return bySev(a) - bySev(b) || b.createdAt - a.createdAt;
        case "newest":   return b.createdAt - a.createdAt;
        case "oldest":   return a.createdAt - b.createdAt;
        case "account":  return String(a.account).localeCompare(String(b.account)) || bySev(a) - bySev(b);
        default: {
          // Most overdue first. Resolved tickets sink; among the rest, the
          // smallest (most negative) remaining time is the most urgent.
          const sa = window.NS.slaState(a, now), sb = window.NS.slaState(b, now);
          const rank = (s) => (s.state === "resolved" ? 1 : 0);
          return rank(sa) - rank(sb) || sa.ms - sb.ms;
        }
      }
    });
    return out;
  }, [filed, q, sevs, account, component, status, sort]);

  const open = filed.filter((t) => t.statusCategory !== "Done");
  const breached = open.filter((t) => window.NS.slaState(t).state === "breached");
  const urgent = open.filter((t) => window.NS.sev(t.severity).rank <= 2);

  const toggleSev = (c) => setSevs((v) => (v.indexOf(c) >= 0 ? v.filter((x) => x !== c) : v.concat(c)));
  const clear = () => { setQ(""); setSevs([]); setAccount(""); setComponent(""); setStatus("open"); };
  const filtering = q || sevs.length || account || component || status !== "open";

  return (
    <div>
      <div className="page-head">
        <div className="eyebrow">Triage</div>
        <h1 className="page-title">In Jira</h1>
        <p className="page-sub">Validated tickets, live from Jira. SEV1/SEV2 also ping the urgent Slack channel, and anything past its promised update time gets re-nagged on its own cadence.</p>
      </div>

      <div className="grid grid-4" style={{ marginBottom: 22 }}>
        <div className="card stat"><span className="stat-label">Open</span><span className="stat-value">{open.length}</span></div>
        <div className="card stat"><span className="stat-label">Urgent (SEV1–2)</span><span className="stat-value" style={{ color: urgent.length ? "var(--sev2)" : "var(--text)" }}>{urgent.length}</span></div>
        <div className="card stat"><span className="stat-label">Past SLA</span><span className="stat-value" style={{ color: breached.length ? "var(--sev1)" : "var(--text)" }}>{breached.length}</span></div>
        <div className="card stat"><span className="stat-label">Accounts</span><span className="stat-value">{accounts.length}</span></div>
      </div>

      <div className="filters">
        <input className="fsearch" placeholder="Search key, title, reporter, account…"
          value={q} onChange={(e) => setQ(e.target.value)} />
        <div className="fchips">
          {window.NS.SEV_ORDER.map((c) => (
            <Chip key={c} on={sevs.indexOf(c) >= 0} onClick={() => toggleSev(c)} title={window.NS.sev(c).rubric}>
              {window.NS.sev(c).emoji} {c}
            </Chip>
          ))}
        </div>
        <select className="fsel" value={account} onChange={(e) => setAccount(e.target.value)}>
          <option value="">All accounts</option>
          {accounts.map((a) => <option key={a} value={a}>{a}</option>)}
        </select>
        <select className="fsel" value={component} onChange={(e) => setComponent(e.target.value)}>
          <option value="">All areas</option>
          {components.map((c) => <option key={c} value={c}>{c}</option>)}
        </select>
        <select className="fsel" value={status} onChange={(e) => setStatus(e.target.value)}>
          <option value="open">Open</option>
          <option value="done">Resolved</option>
          <option value="all">All</option>
        </select>
        <select className="fsel" value={sort} onChange={(e) => setSort(e.target.value)}>
          {SORTS.map((s) => <option key={s.key} value={s.key}>Sort: {s.label}</option>)}
        </select>
        <Chip on={group} onClick={() => setGroup((v) => !v)} title="Group rows by severity">Group</Chip>
        {filtering ? <button className="btn btn-ghost btn-sm" onClick={clear}>Clear</button> : null}
      </div>

      <div className="fcount">{rows.length} {rows.length === 1 ? "ticket" : "tickets"}{filtering ? " match" : ""}</div>

      {!rows.length && <div className="pq-empty">No tickets match these filters.</div>}

      {group
        ? window.NS.SEV_ORDER.map((code) => {
            const g = rows.filter((t) => t.severity === code);
            if (!g.length) return null;
            const s = window.NS.sev(code);
            return (
              <div key={code} style={{ marginBottom: 20 }}>
                <div className="eyebrow" style={{ marginBottom: 10 }}>{s.emoji} {s.code} · {s.label} · Jira {s.jiraPriority}</div>
                <div className="ticket">{g.map((t) => <TicketCard key={t.key} ticket={t} mode="admin" />)}</div>
              </div>
            );
          })
        : <div className="ticket">{rows.map((t) => <TicketCard key={t.key} ticket={t} mode="admin" />)}</div>}
    </div>
  );
}

function uniq(list) { return [...new Set(list.filter(Boolean))].sort(); }

window.TriageBoard = TriageBoard;
