// Closed Deals + New Client Tracker screens
// Backed by REAL data from Updated Scott Module Stat Tracker - 2026.xlsx
//   - Harvey Closed Deals tab  -> F.CLOSED
//   - New Client Tracker tab   -> F.NEW_CLIENTS

// ----------------- Closed Deals -----------------

function ClosedScreen({ scope, period, setPeriod, year, setYear, setScope }) {
  const F = window.VAULT_FIRM;
  const { fmtUSD, fmtNum } = window.VaultUtils;

  // Closed Deals defaults to YTD on first mount so the user sees all of 2026's deals.
  const ranOnce = useRef(false);
  useEffect(() => {
    if (ranOnce.current) return;
    ranOnce.current = true;
    if (period.kind === "trailing") setPeriod({ kind: "year" });
  }, []);

  // Raw-USD formatter (fee field is in raw dollars, not millions).
  // 1,250,000 -> "$1.25M"; 670,000 -> "$670K"; 12,345 -> "$12.3K".
  const fmtFeeUSD = (n) => {
    if (n == null) return "—";
    const sign = n < 0 ? "-" : "";
    const v = Math.abs(n);
    if (v >= 1e6)  return sign + "$" + (v / 1e6).toFixed(v >= 1e7 ? 1 : 2) + "M";
    if (v >= 1e3)  return sign + "$" + Math.round(v / 1e3) + "K";
    return sign + "$" + Math.round(v);
  };
  const [sort, setSort] = useState({ col: "closeDate", dir: "desc" });
  const [filters, setFilters] = useState({ type: [], dm: [], buyer: [] });
  const [search, setSearch] = useState("");
  const [recordOpen, setRecordOpen] = useState(false);
  const [extraDeals, setExtraDeals] = useState([]); // user-added closed deals (session-local)

  // Filter by period + scope
  const inPeriod = useCallback((d) => {
    if (!d.closeDate) return false;
    const dt = new Date(d.closeDate);
    if (period.kind === "quarter") {
      const minMo = (period.q - 1) * 3, maxMo = period.q * 3;
      return dt.getUTCFullYear() === year && dt.getUTCMonth() >= minMo && dt.getUTCMonth() < maxMo;
    }
    if (period.kind === "year") return dt.getUTCFullYear() === year;
    if (period.kind === "trailing") {
      const today = new Date("2026-05-08");
      const cutoff = new Date(today); cutoff.setUTCDate(cutoff.getUTCDate() - period.weeks * 7);
      return dt >= cutoff;
    }
    return true;
  }, [period, year]);

  const dmIds = (d) => [d.dm1, d.dm2, d.dm3].filter(Boolean);

  const scoped = useMemo(() => {
    let out = [...extraDeals, ...F.CLOSED].filter(inPeriod);

    // Scope: any of the deal's DMs must match the selected scope
    if (scope.module) {
      const subs = new Set(F.SUBTEAMS.filter(s => s.moduleId === scope.module).map(s => s.id));
      out = out.filter(d => dmIds(d).some(id => subs.has(F.PEOPLE_BY_ID[id]?.subteam)));
    }
    if (scope.subteam) {
      out = out.filter(d => dmIds(d).some(id => F.PEOPLE_BY_ID[id]?.subteam === scope.subteam));
    }
    if (scope.individuals.length) {
      const set = new Set(scope.individuals);
      out = out.filter(d => dmIds(d).some(id => set.has(id)));
    }
    return out;
  }, [scope, inPeriod]);

  // Compute filter options BEFORE column filters (so user can see all)
  const typeOptions = useMemo(() => {
    const counts = {};
    scoped.forEach(d => { counts[d.typeRaw] = (counts[d.typeRaw] || 0) + 1; });
    return Object.entries(counts).map(([v, n]) => ({ value: v, label: v.replace(/\b\w/g, c => c.toUpperCase()), count: n }));
  }, [scoped]);
  const dmOptions = useMemo(() => {
    const counts = {};
    scoped.forEach(d => dmIds(d).forEach(id => { if (id) counts[id] = (counts[id] || 0) + 1; }));
    return Object.entries(counts)
      .map(([id, n]) => ({ value: id, label: F.PEOPLE_BY_ID[id]?.name || id, count: n }))
      .sort((a, b) => b.count - a.count);
  }, [scoped]);
  const buyerOptions = useMemo(() => {
    const counts = {};
    scoped.forEach(d => { if (d.buyer) counts[d.buyer] = (counts[d.buyer] || 0) + 1; });
    return Object.entries(counts)
      .map(([v, n]) => ({ value: v, label: v, count: n }))
      .sort((a, b) => b.count - a.count);
  }, [scoped]);

  // Apply column filters + search
  const filtered = useMemo(() => {
    let out = scoped;
    if (filters.type.length)  out = out.filter(d => filters.type.includes(d.typeRaw));
    if (filters.dm.length)    out = out.filter(d => dmIds(d).some(id => filters.dm.includes(id)));
    if (filters.buyer.length) out = out.filter(d => filters.buyer.includes(d.buyer));
    if (search.trim()) {
      const q = search.toLowerCase();
      out = out.filter(d =>
        (d.name || "").toLowerCase().includes(q) ||
        (d.buyer || "").toLowerCase().includes(q) ||
        dmIds(d).some(id => (F.PEOPLE_BY_ID[id]?.name || "").toLowerCase().includes(q))
      );
    }
    // Sort
    const cmp = (a, b) => {
      let av, bv;
      switch (sort.col) {
        case "name":      av = a.name || "";       bv = b.name || ""; break;
        case "type":      av = a.typeRaw || "";    bv = b.typeRaw || ""; break;
        case "buyer":     av = a.buyer || "";      bv = b.buyer || ""; break;
        case "tev":       av = a.tev ?? -Infinity; bv = b.tev ?? -Infinity; break;
        case "fee":       av = a.fee ?? -Infinity; bv = b.fee ?? -Infinity; break;
        case "closeDate": default:
          av = a.closeDate || ""; bv = b.closeDate || "";
      }
      if (av < bv) return sort.dir === "asc" ? -1 : 1;
      if (av > bv) return sort.dir === "asc" ?  1 : -1;
      return 0;
    };
    return [...out].sort(cmp);
  }, [scoped, filters, search, sort]);

  const totals = useMemo(() => {
    const earnouts  = filtered.filter(d => d.typeRaw === "earnout");
    const realDeals = filtered.filter(d => d.typeRaw !== "earnout"); // add-on + platform + placement
    return {
      dealsCount: realDeals.length,
      earnoutCount: earnouts.length,
      tev:       realDeals.reduce((s, d) => s + (d.tev || 0), 0), // earnouts have no incremental TEV
      fee:       filtered.reduce((s, d) => s + (d.fee || 0), 0),  // include earnout fees
      earnoutFee: earnouts.reduce((s, d) => s + (d.fee || 0), 0),
      platform:  filtered.filter(d => d.typeRaw === "platform").length,
      addon:     filtered.filter(d => d.typeRaw === "add-on").length,
      placement: filtered.filter(d => d.typeRaw === "placement").length,
    };
  }, [filtered]);

  const toggleSort = (col) => setSort(s => s.col === col ? { col, dir: s.dir === "asc" ? "desc" : "asc" } : { col, dir: col === "closeDate" || col === "tev" || col === "fee" ? "desc" : "asc" });

  const setFilter = (key, vals) => setFilters(f => ({ ...f, [key]: vals }));
  const clearFilter = (key) => setFilters(f => ({ ...f, [key]: [] }));
  const clearAll = () => { setFilters({ type: [], dm: [], buyer: [] }); setSearch(""); };

  const activeChips = [
    ...filters.type.map(v => ({ key: "type", value: v, label: "Type · " + v })),
    ...filters.dm.map(v => ({ key: "dm",   value: v, label: "DM · "   + (F.PEOPLE_BY_ID[v]?.name || v) })),
    ...filters.buyer.map(v => ({ key: "buyer", value: v, label: "Buyer · " + v })),
  ];

  return (
    <div style={{ padding: "20px 28px 60px" }}>
      <div className="row" style={{ justifyContent: "space-between", flexWrap: "wrap", gap: 14, marginBottom: 18 }}>
        <window.ScopeFilters scope={scope} setScope={setScope}/>
        <div className="row" style={{ gap: 10 }}>
          <button className="btn primary" onClick={() => setRecordOpen(true)}>
            <window.Icon.plus/> Record New Closed Deal
          </button>
          <window.VaultPeriod.PeriodSelector value={period} onChange={setPeriod} year={year} onYearChange={setYear}/>
        </div>
      </div>

      {recordOpen && <RecordClosedDealModal onClose={() => setRecordOpen(false)} onSave={(deal) => {
        setExtraDeals(d => [deal, ...d]);
        setRecordOpen(false);
      }}/>}

      {/* Summary tiles */}
      <div style={{ display: "grid", gridTemplateColumns: "repeat(4, 1fr)", gap: 12, marginBottom: 12 }}>
        <SumTile label="Closed Deals"    value={fmtNum(totals.dealsCount)} sub={`${totals.platform} Platform · ${totals.addon} Add-On · ${totals.placement} Placement`}/>
        <SumTile label="Aggregate TEV"   value={"$" + totals.tev.toFixed(0) + "M"} sub="Add-On + Platform + Placement"/>
        <SumTile label="Aggregate Fees"  value={fmtFeeUSD(totals.fee)} accent sub={`incl. ${fmtFeeUSD(totals.earnoutFee)} earnout`}/>
        <SumTile label="Earnouts"        value={fmtNum(totals.earnoutCount)} sub="Deferred fees from prior closes"/>
      </div>

      {/* Search + active filter chips */}
      <div className="row" style={{ gap: 10, marginBottom: 12, flexWrap: "wrap" }}>
        <div style={{ position: "relative", minWidth: 240 }}>
          <input className="input" placeholder="Search deal, buyer, or DM…" value={search} onChange={e => setSearch(e.target.value)} style={{ paddingLeft: 32, width: 280 }}/>
          <span style={{ position: "absolute", left: 10, top: "50%", transform: "translateY(-50%)", color: "var(--muted)" }}><window.Icon.search/></span>
        </div>
        {activeChips.map((c, i) => (
          <span key={c.key + c.value + i} className="pill" style={{ paddingRight: 4, cursor: "default" }}>
            {c.label}
            <button onClick={() => setFilter(c.key, filters[c.key].filter(v => v !== c.value))}
              style={{ marginLeft: 6, background: "transparent", border: 0, color: "var(--muted)", cursor: "pointer", fontSize: 14, lineHeight: 1 }}>×</button>
          </span>
        ))}
        {activeChips.length > 0 && <button className="btn ghost small" onClick={clearAll}>Clear all</button>}
      </div>

      {/* List */}
      <div className="card" style={{ overflow: "hidden" }}>
        <div style={{ overflowX: "auto" }}>
          <table className="dt" style={{ minWidth: 1100 }}>
            <thead><tr>
              <SortFilterTh col="name"      sort={sort} onSort={toggleSort}>Deal</SortFilterTh>
              <SortFilterTh col="type"      sort={sort} onSort={toggleSort} options={typeOptions} selected={filters.type} onChange={v => setFilter("type", v)}>Type</SortFilterTh>
              <th>DMs <FilterMenu options={dmOptions} selected={filters.dm} onChange={v => setFilter("dm", v)} title="Filter DMs"/></th>
              <SortFilterTh col="buyer"     sort={sort} onSort={toggleSort} options={buyerOptions} selected={filters.buyer} onChange={v => setFilter("buyer", v)}>Buyer</SortFilterTh>
              <SortFilterTh col="tev"       sort={sort} onSort={toggleSort} align="r">TEV</SortFilterTh>
              <SortFilterTh col="fee"       sort={sort} onSort={toggleSort} align="r">Fee</SortFilterTh>
              <SortFilterTh col="closeDate" sort={sort} onSort={toggleSort} align="r">Closed</SortFilterTh>
            </tr></thead>
            <tbody>
              {filtered.map(d => {
                const tone =
                  d.typeRaw === "platform"  ? "info"   :
                  d.typeRaw === "earnout"   ? "ok"     :
                  d.typeRaw === "placement" ? "accent" :
                                              "warn";
                const typeLabel = d.typeRaw === "add-on" ? "Add-On" : d.typeRaw.replace(/\b\w/g, c => c.toUpperCase());
                return (
                  <tr key={d.id}>
                    <td><div style={{ fontWeight: 600 }}>{d.name}{d.synth && <window.SynthTag/>}</div></td>
                    <td><span className={`pill ${tone}`}><span className="dot"/>{typeLabel}</span></td>
                    <td>
                      <window.AvatarStack ids={dmIds(d)} size={22}/>
                    </td>
                    <td className="small">{d.buyer}</td>
                    <td className="r mono">{d.tev != null ? "$" + d.tev.toFixed(d.tev < 10 ? 2 : 1) + "M" : "—"}</td>
                    <td className="r mono" style={{ color: "var(--accent)", fontWeight: 600 }}>{d.fee != null ? fmtFeeUSD(d.fee) : "—"}</td>
                    <td className="r mono small">{d.closeDate ? new Date(d.closeDate).toLocaleDateString("en-US", { month: "short", day: "numeric", year: "2-digit" }) : "—"}</td>
                  </tr>
                );
              })}
              {filtered.length === 0 && <tr><td colSpan={7} className="muted" style={{ textAlign: "center", padding: 24 }}>No closed deals match this period & scope.</td></tr>}
            </tbody>
          </table>
        </div>
        <div className="row" style={{ padding: "10px 14px", borderTop: "1px solid var(--line-2)", justifyContent: "space-between" }}>
          <span className="muted small">Showing {filtered.length} of {F.CLOSED.length} closed deals</span>
          <span className="muted small mono">Source: Harvey Closed Deals · Updated Scott Module Stat Tracker - 2026.xlsx</span>
        </div>
      </div>
    </div>
  );
}

function SortFilterTh({ col, sort, onSort, children, align, options, selected, onChange }) {
  const active = sort.col === col;
  const arrow = !active ? null : sort.dir === "asc" ? "▲" : "▼";
  return (
    <th className={align === "r" ? "r" : ""}>
      <button onClick={() => onSort(col)} className="th-sort">
        {children}{arrow && <span style={{ marginLeft: 4, fontSize: 9 }}>{arrow}</span>}
      </button>
      {options && <FilterMenu options={options} selected={selected} onChange={onChange} title={"Filter " + (typeof children === "string" ? children : col)}/>}
    </th>
  );
}

function FilterMenu({ options, selected, onChange, title }) {
  const [open, setOpen] = useState(false);
  const [q, setQ] = useState("");
  const ref = useRef(null);
  useEffect(() => {
    if (!open) return;
    const onDoc = e => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    document.addEventListener("mousedown", onDoc);
    return () => document.removeEventListener("mousedown", onDoc);
  }, [open]);

  const filtered = options.filter(o => !q || o.label.toLowerCase().includes(q.toLowerCase()));
  const active = selected.length > 0;
  return (
    <span ref={ref} style={{ position: "relative", marginLeft: 4 }}>
      <button onClick={() => setOpen(o => !o)} className={"filter-btn" + (active ? " active" : "")} title={title}>
        <svg width="11" height="11" viewBox="0 0 12 12" fill="none"><path d="M1 2.5h10L7.5 7v3l-3 1V7L1 2.5Z" stroke="currentColor" strokeWidth="1.2" strokeLinejoin="round" fill={active ? "currentColor" : "none"}/></svg>
        {active && <span style={{ marginLeft: 3, fontSize: 9, fontWeight: 600 }}>{selected.length}</span>}
      </button>
      {open && (
        <div className="filter-menu" style={{ position: "absolute", top: "calc(100% + 4px)", right: 0, zIndex: 50, width: 240, background: "var(--bg)", border: "1px solid var(--line)", borderRadius: 8, boxShadow: "var(--shadow-md)", padding: 8 }}>
          <input className="input small" placeholder="Search…" value={q} onChange={e => setQ(e.target.value)} style={{ width: "100%", marginBottom: 6 }} autoFocus/>
          <div style={{ maxHeight: 240, overflowY: "auto", marginBottom: 6 }}>
            {filtered.map(o => (
              <label key={o.value} className="row" style={{ gap: 8, padding: "4px 6px", borderRadius: 4, cursor: "pointer", fontSize: 13 }}>
                <input type="checkbox" checked={selected.includes(o.value)} onChange={e => {
                  if (e.target.checked) onChange([...selected, o.value]);
                  else onChange(selected.filter(v => v !== o.value));
                }}/>
                <span style={{ flex: 1 }}>{o.label}</span>
                <span className="muted small mono">{o.count}</span>
              </label>
            ))}
            {filtered.length === 0 && <div className="muted small" style={{ padding: 6 }}>No matches</div>}
          </div>
          <div className="row" style={{ justifyContent: "space-between", borderTop: "1px solid var(--line-2)", paddingTop: 6 }}>
            <button className="btn ghost small" onClick={() => onChange([])}>Clear</button>
            <button className="btn small" onClick={() => setOpen(false)}>Done</button>
          </div>
        </div>
      )}
    </span>
  );
}

function SumTile({ label, value, sub, accent }) {
  return (
    <div className="card" style={{ padding: 14 }}>
      <div className="micro">{label}</div>
      <div className="mono display" style={{
        fontSize: 24, fontWeight: 500, marginTop: 4,
        color: accent ? "var(--accent)" : "var(--ink)",
        letterSpacing: "-.01em",
      }}>{value}</div>
      {sub && <div className="muted small" style={{ marginTop: 2, fontSize: 11 }}>{sub}</div>}
    </div>
  );
}

window.ClosedScreen = ClosedScreen;

// ----------------- Record New Closed Deal modal -----------------

function RecordClosedDealModal({ onClose, onSave }) {
  const F = window.VAULT_FIRM;
  const today = new Date().toISOString().slice(0, 10);
  const [form, setForm] = useState({
    name: "", buyer: "", dm1: "", dm2: "", dm3: "",
    tev: "", fee: "", closeDate: today, type: "add-on",
  });
  const set = (k, v) => setForm(f => ({ ...f, [k]: v }));

  const people = F.PEOPLE.slice().sort((a, b) => a.name.localeCompare(b.name));
  const canSave = form.name.trim() && form.dm1;

  const submit = () => {
    if (!canSave) return;
    const id = "C-NEW-" + Date.now().toString(36);
    onSave({
      id,
      name: form.name.trim(),
      buyer: form.buyer.trim(),
      dm1: form.dm1 || null,
      dm2: form.dm2 || null,
      dm3: form.dm3 || null,
      tev: form.tev !== "" ? parseFloat(form.tev) : null,
      fee: form.fee !== "" ? parseFloat(form.fee) : null,
      closeDate: form.closeDate,
      type: form.type === "add-on" ? "addon" : form.type,
      typeRaw: form.type,
      status: "closed",
      subteam: F.PEOPLE_BY_ID[form.dm1]?.subteam || null,
      synth: false,
      isNew: true,
    });
  };

  return (
    <div style={{
      position: "fixed", inset: 0, background: "rgba(20,19,15,0.45)",
      zIndex: 100, display: "flex", alignItems: "center", justifyContent: "center",
    }} onClick={onClose}>
      <div onClick={e => e.stopPropagation()} style={{
        background: "var(--bg)", border: "1px solid var(--line)", borderRadius: 12,
        width: 560, maxWidth: "92vw", maxHeight: "90vh", overflow: "auto",
        boxShadow: "var(--shadow-lg, 0 20px 50px rgba(0,0,0,0.25))",
      }}>
        <div className="row" style={{ padding: "16px 20px", borderBottom: "1px solid var(--line-2)", justifyContent: "space-between" }}>
          <h3 className="display" style={{ margin: 0, fontSize: 18, fontWeight: 400 }}>Record New Closed Deal</h3>
          <button className="btn ghost small" onClick={onClose}>✕</button>
        </div>

        <div style={{ padding: 20, display: "grid", gap: 14 }}>
          <Field label="Target Company *">
            <input className="input" autoFocus value={form.name} onChange={e => set("name", e.target.value)} placeholder="e.g. Acme Industrial"/>
          </Field>
          <Field label="Buyer">
            <input className="input" value={form.buyer} onChange={e => set("buyer", e.target.value)} placeholder="e.g. Cornerstone Equity"/>
          </Field>
          <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12 }}>
            <Field label="TEV ($M)">
              <input className="input" type="number" step="0.1" value={form.tev} onChange={e => set("tev", e.target.value)} placeholder="e.g. 45"/>
            </Field>
            <Field label="Fee (USD)">
              <input className="input" type="number" step="1000" value={form.fee} onChange={e => set("fee", e.target.value)} placeholder="e.g. 670000"/>
            </Field>
          </div>
          <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12 }}>
            <Field label="Close Date">
              <input className="input" type="date" value={form.closeDate} onChange={e => set("closeDate", e.target.value)}/>
            </Field>
            <Field label="Type">
              <select className="input" value={form.type} onChange={e => set("type", e.target.value)}>
                <option value="add-on">Add-On</option>
                <option value="platform">Platform</option>
                <option value="placement">Placement</option>
                <option value="earnout">Earnout</option>
              </select>
            </Field>
          </div>
          <Field label="Lead Dealmaker (DM1) *">
            <PeoplePicker value={form.dm1} onChange={v => set("dm1", v)} people={people}/>
          </Field>
          <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12 }}>
            <Field label="DM2">
              <PeoplePicker value={form.dm2} onChange={v => set("dm2", v)} people={people}/>
            </Field>
            <Field label="DM3">
              <PeoplePicker value={form.dm3} onChange={v => set("dm3", v)} people={people}/>
            </Field>
          </div>
        </div>

        <div className="row" style={{ padding: "12px 20px", borderTop: "1px solid var(--line-2)", justifyContent: "flex-end", gap: 8 }}>
          <button className="btn ghost" onClick={onClose}>Cancel</button>
          <button className="btn primary" onClick={submit} disabled={!canSave} style={!canSave ? { opacity: 0.5, cursor: "not-allowed" } : null}>
            Record Close
          </button>
        </div>
      </div>
    </div>
  );
}

function Field({ label, children }) {
  return (
    <label style={{ display: "block" }}>
      <div className="micro" style={{ marginBottom: 5 }}>{label}</div>
      {children}
    </label>
  );
}

function PeoplePicker({ value, onChange, people }) {
  return (
    <select className="input" value={value || ""} onChange={e => onChange(e.target.value)}>
      <option value="">— Select —</option>
      {people.map(p => <option key={p.id} value={p.id}>{p.name}</option>)}
    </select>
  );
}

// ----------------- New Client Tracker -----------------

function NewClientsScreen({ scope, setScope }) {
  const F = window.VAULT_FIRM;
  const [rows, setRows] = useState(() => F.NEW_CLIENTS.map(r => ({ ...r })));
  const [sort, setSort] = useState({ col: "nextActionDate", dir: "asc" });
  const [filters, setFilters] = useState({ stage: [], owner: [], market: [], service: [] });
  const [search, setSearch] = useState("");

  // Dropdown choice sets derived from current data
  const stageChoices = useMemo(() => {
    const set = new Set(rows.map(r => r.stageLabel).filter(Boolean));
    // common stages we always offer
    ["Intro","Pitch","In EL","Active Project","Signed","Lost","Killed","Dormant"].forEach(s => set.add(s));
    return [...set].sort();
  }, [rows]);
  const marketChoices  = useMemo(() => [...new Set(rows.map(r => r.market).filter(Boolean))].sort(),  [rows]);
  const serviceChoices = useMemo(() => [...new Set(rows.map(r => r.service).filter(Boolean))].sort(), [rows]);
  const geoChoices     = useMemo(() => [...new Set(rows.map(r => r.geography).filter(Boolean))].sort(), [rows]);
  const ownerChoices = F.PEOPLE;

  const updateRow = (id, patch) => setRows(rs => rs.map(r => r.id === id ? { ...r, ...patch } : r));
  const removeRow = (id) => { if (confirm("Remove this prospect?")) setRows(rs => rs.filter(r => r.id !== id)); };
  const addRow = () => {
    const id = "N-" + Date.now().toString(36);
    setRows(rs => [{
      id, project: "New Prospect", client: "", stageLabel: "Intro", stageCode: 5,
      origDate: new Date().toISOString().slice(0,10),
      nextActionDate: "",
      owner: null, ownerLabel: "",
      market: "", service: "", geography: "", notes: "",
    }, ...rs]);
  };

  // Scope filter
  const scoped = useMemo(() => {
    let out = rows;
    if (scope.individuals.length) out = out.filter(r => scope.individuals.includes(r.owner));
    else if (scope.subteam)       out = out.filter(r => F.PEOPLE_BY_ID[r.owner]?.subteam === scope.subteam);
    else if (scope.module) {
      const subs = new Set(F.SUBTEAMS.filter(s => s.moduleId === scope.module).map(s => s.id));
      out = out.filter(r => subs.has(F.PEOPLE_BY_ID[r.owner]?.subteam));
    }
    return out;
  }, [rows, scope]);

  const stageOptions = useMemo(() => {
    const counts = {};
    scoped.forEach(r => { const k = r.stageLabel; counts[k] = (counts[k] || 0) + 1; });
    return Object.entries(counts).map(([v, n]) => ({ value: v, label: v, count: n })).sort((a, b) => b.count - a.count);
  }, [scoped]);
  const ownerOptions = useMemo(() => {
    const counts = {};
    scoped.forEach(r => { const k = r.ownerLabel || "Unassigned"; counts[k] = (counts[k] || 0) + 1; });
    return Object.entries(counts).map(([v, n]) => ({ value: v, label: v, count: n })).sort((a, b) => b.count - a.count);
  }, [scoped]);
  const marketOptions = useMemo(() => {
    const counts = {};
    scoped.forEach(r => { if (r.market) counts[r.market] = (counts[r.market] || 0) + 1; });
    return Object.entries(counts).map(([v, n]) => ({ value: v, label: v, count: n })).sort((a, b) => b.count - a.count);
  }, [scoped]);
  const serviceOptions = useMemo(() => {
    const counts = {};
    scoped.forEach(r => { if (r.service) counts[r.service] = (counts[r.service] || 0) + 1; });
    return Object.entries(counts).map(([v, n]) => ({ value: v, label: v, count: n })).sort((a, b) => b.count - a.count);
  }, [scoped]);

  const filtered = useMemo(() => {
    let out = scoped;
    if (filters.stage.length)   out = out.filter(r => filters.stage.includes(r.stageLabel));
    if (filters.owner.length)   out = out.filter(r => filters.owner.includes(r.ownerLabel || "Unassigned"));
    if (filters.market.length)  out = out.filter(r => filters.market.includes(r.market));
    if (filters.service.length) out = out.filter(r => filters.service.includes(r.service));
    if (search.trim()) {
      const q = search.toLowerCase();
      out = out.filter(r =>
        (r.project || "").toLowerCase().includes(q) ||
        (r.client || "").toLowerCase().includes(q) ||
        (r.notes || "").toLowerCase().includes(q) ||
        (r.market || "").toLowerCase().includes(q) ||
        (r.service || "").toLowerCase().includes(q) ||
        (r.geography || "").toLowerCase().includes(q)
      );
    }
    const cmp = (a, b) => {
      let av, bv;
      switch (sort.col) {
        case "project":  av = a.project || "";   bv = b.project || ""; break;
        case "client":   av = a.client || "";    bv = b.client || ""; break;
        case "stage":    av = a.stageCode ?? 99; bv = b.stageCode ?? 99; break;
        case "origDate": av = a.origDate || "";  bv = b.origDate || ""; break;
        case "owner":    av = a.ownerLabel || ""; bv = b.ownerLabel || ""; break;
        case "market":   av = a.market || "";    bv = b.market || ""; break;
        case "service":  av = a.service || "";   bv = b.service || ""; break;
        case "nextActionDate": default:
          av = a.nextActionDate || "9999"; bv = b.nextActionDate || "9999";
      }
      if (av < bv) return sort.dir === "asc" ? -1 : 1;
      if (av > bv) return sort.dir === "asc" ?  1 : -1;
      return 0;
    };
    return [...out].sort(cmp);
  }, [scoped, filters, search, sort]);

  const summary = useMemo(() => {
    const today = new Date("2026-05-08");
    const overdue = filtered.filter(r => r.nextActionDate && new Date(r.nextActionDate) < today).length;
    const activeProjects = filtered.filter(r => r.stageLabel && /Active|Pitched|Signed/i.test(r.stageLabel)).length;
    const inEL = filtered.filter(r => r.stageLabel && /EL|Engagement/i.test(r.stageLabel)).length;
    return { total: filtered.length, overdue, activeProjects, inEL };
  }, [filtered]);

  const toggleSort = (col) => setSort(s => s.col === col ? { col, dir: s.dir === "asc" ? "desc" : "asc" } : { col, dir: "asc" });
  const setFilter = (key, vals) => setFilters(f => ({ ...f, [key]: vals }));
  const clearAll = () => { setFilters({ stage: [], owner: [], market: [], service: [] }); setSearch(""); };
  const activeCount = Object.values(filters).reduce((s, v) => s + v.length, 0);

  const fmtDate = (s) => s ? new Date(s).toLocaleDateString("en-US", { month: "short", day: "numeric", year: "2-digit" }) : "—";
  const today = new Date("2026-05-08");

  const stageTone = (stage, code) => {
    if (!stage) return "";
    if (/Active|Signed/i.test(stage)) return "ok";
    if (/EL|Engagement/i.test(stage)) return "warn";
    if (/Pitch/i.test(stage)) return "info";
    if (/Lost|Killed|Dead/i.test(stage)) return "danger";
    if (code >= 9) return "ok";
    if (code >= 6) return "info";
    return "";
  };

  return (
    <div style={{ padding: "20px 28px 60px" }}>
      <div className="row" style={{ justifyContent: "space-between", flexWrap: "wrap", gap: 14, marginBottom: 14 }}>
        <window.ScopeFilters scope={scope} setScope={setScope}/>
        <span className="muted small mono">{filtered.length} prospects</span>
      </div>

      {/* Summary tiles */}
      <div style={{ display: "grid", gridTemplateColumns: "repeat(4, 1fr)", gap: 12, marginBottom: 18 }}>
        <SumTile label="Live Prospects"   value={summary.total}/>
        <SumTile label="In EL / Redlines" value={summary.inEL} accent/>
        <SumTile label="Active Projects"  value={summary.activeProjects}/>
        <SumTile label="Past Next Action" value={summary.overdue}/>
      </div>

      {/* Search + active filter chips */}
      <div className="row" style={{ gap: 10, marginBottom: 12, flexWrap: "wrap" }}>
        <div style={{ position: "relative", minWidth: 240 }}>
          <input className="input" placeholder="Search project, client, market, notes…" value={search} onChange={e => setSearch(e.target.value)} style={{ paddingLeft: 32, width: 320 }}/>
          <span style={{ position: "absolute", left: 10, top: "50%", transform: "translateY(-50%)", color: "var(--muted)" }}><window.Icon.search/></span>
        </div>
        {activeCount > 0 && <button className="btn ghost small" onClick={clearAll}>Clear filters ({activeCount})</button>}
        <span className="stretch"/>
        <button className="btn primary sm" onClick={addRow}>+ Add prospect</button>
      </div>

      <div className="card" style={{ overflow: "hidden" }}>
        <div style={{ overflowX: "auto" }}>
          <table className="dt" style={{ minWidth: 1400 }}>
            <thead><tr>
              <SortFilterTh col="project" sort={sort} onSort={toggleSort}>Project</SortFilterTh>
              <SortFilterTh col="client"  sort={sort} onSort={toggleSort}>Client</SortFilterTh>
              <SortFilterTh col="stage"   sort={sort} onSort={toggleSort} options={stageOptions} selected={filters.stage} onChange={v => setFilter("stage", v)}>Stage</SortFilterTh>
              <SortFilterTh col="origDate" sort={sort} onSort={toggleSort}>Originated</SortFilterTh>
              <SortFilterTh col="nextActionDate" sort={sort} onSort={toggleSort}>Next Action</SortFilterTh>
              <SortFilterTh col="owner"   sort={sort} onSort={toggleSort} options={ownerOptions} selected={filters.owner} onChange={v => setFilter("owner", v)}>Owner</SortFilterTh>
              <SortFilterTh col="market"  sort={sort} onSort={toggleSort} options={marketOptions} selected={filters.market} onChange={v => setFilter("market", v)}>Market</SortFilterTh>
              <SortFilterTh col="service" sort={sort} onSort={toggleSort} options={serviceOptions} selected={filters.service} onChange={v => setFilter("service", v)}>Service Line</SortFilterTh>
              <th>Geography</th>
              <th>Notes</th>
              <th style={{ width: 30 }}/>
            </tr></thead>
            <tbody>
              {filtered.map(r => {
                const tone = stageTone(r.stageLabel, r.stageCode);
                const overdue = r.nextActionDate && new Date(r.nextActionDate) < today;
                const inputStyle = { width: "100%", border: "1px solid transparent", background: "transparent", padding: "3px 5px", fontSize: 12, fontFamily: "inherit", color: "var(--ink)", borderRadius: 4 };
                const focusStyle = (e) => { e.target.style.background = "var(--surface)"; e.target.style.borderColor = "var(--accent)"; };
                const blurStyle  = (e) => { e.target.style.background = "transparent"; e.target.style.borderColor = "transparent"; };
                return (
                  <tr key={r.id}>
                    <td style={{ minWidth: 160 }}>
                      <input style={{ ...inputStyle, fontWeight: 600 }} value={r.project || ""}
                        onChange={e => updateRow(r.id, { project: e.target.value })}
                        onFocus={focusStyle} onBlur={blurStyle}/>
                    </td>
                    <td style={{ minWidth: 140 }}>
                      <input style={inputStyle} value={r.client || ""}
                        onChange={e => updateRow(r.id, { client: e.target.value })}
                        onFocus={focusStyle} onBlur={blurStyle}/>
                    </td>
                    <td style={{ minWidth: 150 }}>
                      <select value={r.stageLabel || ""}
                        onChange={e => updateRow(r.id, { stageLabel: e.target.value })}
                        style={{ ...inputStyle, padding: "2px 4px" }}>
                        <option value="">—</option>
                        {stageChoices.map(s => <option key={s} value={s}>{s}</option>)}
                      </select>
                    </td>
                    <td style={{ width: 130 }}>
                      <input type="date" value={r.origDate || ""}
                        onChange={e => updateRow(r.id, { origDate: e.target.value })}
                        style={{ ...inputStyle, fontFamily: "var(--f-mono)", fontSize: 11 }}/>
                    </td>
                    <td style={{ width: 130 }}>
                      <input type="date" value={r.nextActionDate || ""}
                        onChange={e => updateRow(r.id, { nextActionDate: e.target.value })}
                        style={{ ...inputStyle, fontFamily: "var(--f-mono)", fontSize: 11, color: overdue ? "var(--danger)" : "var(--ink)", fontWeight: overdue ? 600 : 400 }}/>
                    </td>
                    <td style={{ minWidth: 60, width: 60 }}>
                      <span style={{ position: "relative", display: "inline-flex", alignItems: "center" }} title={r.ownerLabel || "Unassigned"}>
                        {r.owner ? (
                          <window.Avatar id={r.owner}/>
                        ) : (
                          <span className="avatar" style={{ background: "var(--surface-2)", color: "var(--muted)", border: "1px dashed var(--line)" }}>?</span>
                        )}
                        <select value={r.owner || ""}
                          onChange={e => {
                            const pid = e.target.value || null;
                            const p = F.PEOPLE_BY_ID[pid];
                            updateRow(r.id, { owner: pid, ownerLabel: p ? p.name : "" });
                          }}
                          style={{ position: "absolute", inset: 0, opacity: 0, cursor: "pointer", width: "100%", height: "100%", border: "none" }}>
                          <option value="">Unassigned</option>
                          {ownerChoices.map(p => <option key={p.id} value={p.id}>{p.name}</option>)}
                        </select>
                      </span>
                    </td>
                    <td style={{ minWidth: 130 }}>
                      <input list={`mkt-${r.id}`} style={inputStyle} value={r.market || ""}
                        onChange={e => updateRow(r.id, { market: e.target.value })}
                        onFocus={focusStyle} onBlur={blurStyle}/>
                      <datalist id={`mkt-${r.id}`}>{marketChoices.map(s => <option key={s} value={s}/>)}</datalist>
                    </td>
                    <td style={{ minWidth: 130 }}>
                      <input list={`svc-${r.id}`} style={inputStyle} value={r.service || ""}
                        onChange={e => updateRow(r.id, { service: e.target.value })}
                        onFocus={focusStyle} onBlur={blurStyle}/>
                      <datalist id={`svc-${r.id}`}>{serviceChoices.map(s => <option key={s} value={s}/>)}</datalist>
                    </td>
                    <td style={{ minWidth: 120 }}>
                      <input list={`geo-${r.id}`} style={inputStyle} value={r.geography || ""}
                        onChange={e => updateRow(r.id, { geography: e.target.value })}
                        onFocus={focusStyle} onBlur={blurStyle}/>
                      <datalist id={`geo-${r.id}`}>{geoChoices.map(s => <option key={s} value={s}/>)}</datalist>
                    </td>
                    <td style={{ minWidth: 220 }}>
                      <input style={inputStyle} value={r.notes || ""}
                        onChange={e => updateRow(r.id, { notes: e.target.value })}
                        onFocus={focusStyle} onBlur={blurStyle}/>
                    </td>
                    <td style={{ width: 30, textAlign: "center" }}>
                      <button onClick={() => removeRow(r.id)} title="Delete" style={{
                        background: "transparent", border: "none", color: "var(--muted)", cursor: "pointer",
                        fontSize: 14, padding: 4, lineHeight: 1,
                      }} onMouseEnter={e => e.target.style.color = "var(--danger)"} onMouseLeave={e => e.target.style.color = "var(--muted)"}>×</button>
                    </td>
                  </tr>
                );
              })}
              {filtered.length === 0 && <tr><td colSpan={11} className="muted" style={{ textAlign: "center", padding: 24 }}>No prospects match this scope.</td></tr>}
            </tbody>
          </table>
        </div>
        <div className="row" style={{ padding: "10px 14px", borderTop: "1px solid var(--line-2)", justifyContent: "space-between" }}>
          <span className="muted small">Showing {filtered.length} of {rows.length} prospects · click any cell to edit</span>
          <span className="muted small mono">Source: New Client Tracker · Updated Scott Module Stat Tracker - 2026.xlsx</span>
        </div>
      </div>
    </div>
  );
}

window.NewClientsScreen = NewClientsScreen;
