// screens-sector.jsx — Sector Monitor (Project Management step, 7/28).
// Buyer-universe grain per Brian's ruling: sectors are HIS curation (sector_map)
// over real Harvey buyer ids; Harvey's project `category` is a label, not a
// taxonomy. Renders: sector rollups (total universe, most recent OUTREACH — the
// v1.48 admin-noise-free column) with buyer sub-rows, an unmapped-buyer triage
// sorted by universe size, and an explicit Ignore lane so H&C-search / legacy
// relics stop resurfacing. Maintenance SCORE deliberately absent — formula
// awaits Brian's redline; recency tint is the placeholder and says so.
(function () {
  const { useState, useEffect, useMemo } = React;
  const LINE = "#E4E9F0", MUTE = "#8A97A8", INK = "#22303F";
  const MONO = "var(--f-mono, 'IBM Plex Mono', monospace)";
  const PANEL = { background: "#fff", border: `1px solid ${LINE}`, borderRadius: 14, padding: 20, marginBottom: 18 };
  const KICK = { fontFamily: MONO, fontSize: 11, fontWeight: 600, letterSpacing: ".16em", textTransform: "uppercase", color: "#7C8DA1" };

  const daysSince = d => { if (!d) return null; const t = new Date(d + "T00:00:00"); return Math.floor((Date.now() - t.getTime()) / 86400000); };
  const tint = d => { const n = daysSince(d);
    if (n == null) return { bg: "#F4F7FB", fg: "#8A97A8", label: "never" };
    if (n <= 30) return { bg: "#EAF6EF", fg: "#1B7A46", label: n + "d" };
    if (n <= 90) return { bg: "#FBF3E3", fg: "#8A5B08", label: n + "d" };
    return { bg: "#FDF1F1", fg: "#A94A4A", label: n + "d" }; };

  function SectorMonitorScreen({ user }) {
    const [universe, setUniverse] = useState(null);
    const [smap, setSmap] = useState(new Map());
    const [err, setErr] = useState(null);
    const [openSector, setOpenSector] = useState(null);
    const [showIgnored, setShowIgnored] = useState(false);
    useEffect(() => {
      let live = true;
      Promise.all([window.VaultAPI.listSectorUniverse(), window.VaultAPI.listSectorMap()])
        .then(([u, m]) => { if (!live) return;
          setUniverse(u || []);
          setSmap(new Map((m || []).map(x => [String(x.buyerId), x]))); })
        .catch(e => { if (live) setErr(String((e && e.message) || e)); });
      return () => { live = false; };
    }, []);

    async function assign(buyerId, patch) {
      // optimistic; shared table — one person's curation is everyone's
      setSmap(prev => { const m = new Map(prev);
        const cur = m.get(String(buyerId)) || { buyerId: String(buyerId), sector: "", ignored: false };
        m.set(String(buyerId), Object.assign({}, cur, patch)); return m; });
      try { await window.VaultAPI.upsertSectorMapRow(buyerId, patch); }
      catch (e) { window.VaultUI.toast("error", "Save failed \u2014 " + ((e && e.message) || e)); }
    }

    const view = useMemo(() => {
      if (!universe) return null;
      const sectors = new Map(); const unmapped = []; const ignored = [];
      for (const b of universe) {
        const m = smap.get(String(b.buyerId));
        if (m && m.ignored) { ignored.push(b); continue; }
        if (m && m.sector) {
          let s = sectors.get(m.sector);
          if (!s) { s = { name: m.sector, buyers: [], universe: 0, lastOutreach: "" }; sectors.set(m.sector, s); }
          s.buyers.push(b); s.universe += b.universeCount;
          const lo = b.lastOutreachDate || "";
          if (lo > s.lastOutreach) s.lastOutreach = lo;
        } else unmapped.push(b);
      }
      unmapped.sort((a, b) => b.universeCount - a.universeCount);
      const rows = [...sectors.values()].sort((a, b) => b.universe - a.universe);
      rows.forEach(s => s.buyers.sort((a, b) => b.universeCount - a.universeCount));
      return { rows, unmapped, ignored };
    }, [universe, smap]);

    const sectorNames = useMemo(() => view ? [...new Set(view.rows.map(s => s.name))].sort() : [], [view]);

    function BuyerRow({ b, inSector }) {
      const t = tint(b.lastOutreachDate);
      return (
        <div style={{ display: "grid", gridTemplateColumns: "minmax(0,1.6fr) 90px 90px minmax(120px,1fr) 1fr", gap: 12,
          alignItems: "center", padding: "9px 0", borderTop: `1px solid #F1F4F8` }}>
          <span style={{ fontSize: 13.5, color: INK, minWidth: 0, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{b.buyerName || "(unnamed)"}
            <span style={{ fontFamily: MONO, fontSize: 10, color: "#B4C1D2", marginLeft: 7 }}>{b.buyerId}</span></span>
          <span style={{ fontFamily: MONO, fontSize: 12.5, textAlign: "right", color: INK }}>{Number(b.universeCount).toLocaleString()}</span>
          <span style={{ justifySelf: "start" }}>
            <span style={{ fontFamily: MONO, fontSize: 10.5, padding: "2px 8px", borderRadius: 6, background: t.bg, color: t.fg }}
              title={b.lastOutreach ? b.lastOutreach + " \u00b7 " + (b.lastOutreachDate || "") : "no outreach on record"}>{t.label}</span>
          </span>
          <span style={{ fontFamily: MONO, fontSize: 11, color: MUTE, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>
            {b.lastOutreach ? b.lastOutreach + " \u00b7 " + b.lastOutreachDate : "\u2014"}</span>
          <span style={{ display: "flex", gap: 6, justifyContent: "flex-end", flexWrap: "wrap" }}>
            <input list="vault-sector-names" defaultValue={inSector || ""} placeholder="Sector\u2026" key={b.buyerId + ":" + (inSector || "")}
              onBlur={e => { const v = e.target.value.trim(); if (v && v !== (inSector || "")) assign(b.buyerId, { sector: v, ignored: false }); }}
              onKeyDown={e => { if (e.key === "Enter") e.target.blur(); }}
              style={{ fontFamily: "inherit", fontSize: 12, padding: "4px 8px", border: `1px solid ${LINE}`, borderRadius: 7, width: 150 }}/>
            <button onClick={() => assign(b.buyerId, { ignored: true })} title="Ignore \u2014 legacy / search relic; hides from triage for everyone"
              style={{ fontFamily: "inherit", fontSize: 11.5, padding: "4px 9px", border: `1px solid ${LINE}`, borderRadius: 7,
                background: "#fff", color: MUTE, cursor: "pointer" }}>Ignore</button>
          </span>
        </div>
      );
    }

    return (
      <div style={{ padding: "24px 30px 64px" }}>
        {window.PageToolbar && <window.PageToolbar title="Sector Monitor"
          subtitle="Buyer universes by curated sector \u00b7 outreach recency (admin noise excluded)" style={{ marginBottom: 10 }}/>}
        <datalist id="vault-sector-names">{sectorNames.map(n => <option key={n} value={n}/>)}</datalist>
        {err && <div style={{ ...PANEL, color: "#A94A4A", fontSize: 13 }}>Failed to load \u2014 {err}</div>}
        {!err && !view && <div style={{ ...PANEL, color: MUTE, fontSize: 13 }}>Loading universe{"\u2026"}</div>}
        {view && (
          <>
            {view.rows.length > 0 && (
              <div style={PANEL}>
                <div style={{ ...KICK, marginBottom: 6 }}>Sectors {"\u00b7"} {view.rows.length}</div>
                <div style={{ fontSize: 11.5, color: MUTE, marginBottom: 10 }}>
                  Recency tint is a placeholder \u2014 the maintenance score formula ships after redline.</div>
                {view.rows.map(s => {
                  const t = tint(s.lastOutreach); const open = openSector === s.name;
                  return (
                    <div key={s.name} style={{ borderTop: `1px solid ${LINE}`, padding: "4px 0" }}>
                      <button onClick={() => setOpenSector(open ? null : s.name)} style={{ appearance: "none", width: "100%",
                        background: "none", border: "none", padding: "10px 0", cursor: "pointer", display: "grid",
                        gridTemplateColumns: "minmax(0,1.6fr) 90px 90px 1fr auto", gap: 12, alignItems: "center", textAlign: "left", fontFamily: "inherit" }}>
                        <span style={{ fontSize: 14.5, fontWeight: 600, color: INK }}>{s.name}</span>
                        <span style={{ fontFamily: MONO, fontSize: 13, textAlign: "right", color: INK }}>{s.universe.toLocaleString()}</span>
                        <span><span style={{ fontFamily: MONO, fontSize: 10.5, padding: "2px 8px", borderRadius: 6, background: t.bg, color: t.fg }}>{t.label}</span></span>
                        <span style={{ fontSize: 11.5, color: MUTE }}>{s.buyers.length} buyer{s.buyers.length === 1 ? "" : "s"}</span>
                        <span style={{ fontSize: 11, color: "#B4C1D2" }}>{open ? "\u25B4" : "\u25BE"}</span>
                      </button>
                      {open && s.buyers.map(b => <BuyerRow key={b.buyerId} b={b} inSector={s.name}/>)}
                    </div>
                  );
                })}
              </div>
            )}
            <div style={PANEL}>
              <div style={{ ...KICK, marginBottom: 10 }}>Unmapped Buyers {"\u00b7"} {view.unmapped.length} {"\u00b7"} largest first</div>
              {view.unmapped.length === 0 && <div style={{ fontSize: 12.5, color: MUTE }}>Everything is mapped or ignored.</div>}
              {view.unmapped.map(b => <BuyerRow key={b.buyerId} b={b} inSector=""/>)}
            </div>
            <div style={{ ...PANEL, opacity: .8 }}>
              <button onClick={() => setShowIgnored(v => !v)} style={{ appearance: "none", background: "none", border: "none",
                padding: 0, cursor: "pointer", fontFamily: "inherit", ...KICK }}>
                Ignored {"\u00b7"} {view.ignored.length} {showIgnored ? "\u25B4" : "\u25BE"}</button>
              {showIgnored && view.ignored.map(b => (
                <div key={b.buyerId} style={{ display: "flex", gap: 10, alignItems: "center", padding: "8px 0", borderTop: `1px solid #F1F4F8` }}>
                  <span style={{ fontSize: 13, color: MUTE, flex: 1 }}>{b.buyerName} <span style={{ fontFamily: MONO, fontSize: 10, color: "#C6CDD8" }}>{b.buyerId}</span></span>
                  <span style={{ fontFamily: MONO, fontSize: 11.5, color: MUTE }}>{Number(b.universeCount).toLocaleString()}</span>
                  <button onClick={() => assign(b.buyerId, { ignored: false })}
                    style={{ fontFamily: "inherit", fontSize: 11.5, padding: "3px 9px", border: `1px solid ${LINE}`, borderRadius: 7,
                      background: "#fff", color: "#196EA7", cursor: "pointer" }}>Restore</button>
                </div>
              ))}
            </div>
          </>
        )}
      </div>
    );
  }
  window.SectorMonitorScreen = SectorMonitorScreen;
})();
