/* CRM · Account — extra company dossier panels, ported 1:1 from the map modal's
 * renderDossier* functions (index.html). Each panel fetches its own RPC keyed by
 * org_id and renders ONLY when real data is on file (returns null otherwise) —
 * no fabricated rows, no placeholders. Registered on window.CrmPanels[key];
 * AccountDossier renders them in an explicit order. Shared kit on
 * window.CrmPanelKit so the other CrmAccountPanels*.jsx batch files reuse it.
 *
 * Styling uses the same crm.css classes as the rest of the dossier
 * (card/card-head/reg-panel/reg-row/field). The data shapes mirror the map RPCs
 * exactly — see the matching renderDossier* in index.html for the source layout. */

(function () {
  const { useState, useEffect } = React;
  window.CrmPanels = window.CrmPanels || {};

  // Fetch helper: runs an async loader(client, orgId). Returns `undefined` while
  // loading, then the resolved data (or `null` on error / none).
  function usePanelData(loader, orgId) {
    const [d, setD] = useState(undefined);
    useEffect(() => {
      const c = window.ContactIQ && window.ContactIQ.client;
      if (!c || !orgId) { setD(null); return; }
      let alive = true; setD(undefined);
      Promise.resolve(loader(c, orgId))
        .then((data) => { if (alive) setD(data == null ? null : data); })
        .catch(() => { if (alive) setD(null); });
      return () => { alive = false; };
    }, [orgId]);
    return d;
  }
  // RPC convenience: (name) => loader returning the data (array/obj) or null.
  const rpcLoad = (name) => (c, orgId) => c.rpc(name, { p_org_id: orgId }).then(({ data, error }) => (error ? null : data));
  // Edge-function GET convenience (NPPES / USPTO live fetches).
  const fnGet = (path) => (c, orgId) => {
    const base = (window.ContactIQ && window.ContactIQ.SUPABASE_URL) || "";
    const key = (window.ContactIQ && window.ContactIQ.SUPABASE_KEY) || "";
    return fetch(base + path + (path.includes("?") ? "&" : "?") + "org_id=" + orgId,
      { headers: { apikey: key, Authorization: "Bearer " + key } }).then((r) => r.json());
  };

  const money = (n) => (n == null ? null : "$" + Number(n).toLocaleString(undefined, { maximumFractionDigits: 0 }));
  const num = (n) => (n == null ? null : Number(n).toLocaleString());
  const fmtDate = (s) => {
    if (!s) return "";
    const str = String(s);
    if (str.startsWith("0001-") || str.startsWith("1900")) return "";
    const dt = new Date(str);
    return isNaN(dt) ? str.slice(0, 10) : dt.toLocaleDateString("en-US", { year: "numeric", month: "short", day: "numeric" });
  };
  const fmtMonth = (s) => { if (!s) return ""; const dt = new Date(s); return isNaN(dt) ? "" : dt.toLocaleDateString("en-US", { year: "numeric", month: "short" }); };

  // A monospace DOS/source badge for the panel header (matches the map's pill).
  const SrcBadge = ({ children, bg, color }) => (
    <span className="pill" style={{ padding: "1px 7px", fontFamily: "var(--font-mono)", fontSize: "9px", fontWeight: 700, letterSpacing: ".04em", background: bg, color, borderColor: "transparent" }}>{children}</span>
  );
  // Inline colored flag pill (status / type chips).
  const Flag = ({ bg, color, title, children }) => (
    <span className="pill" title={title || ""} style={{ padding: "1px 7px", background: bg, color, borderColor: "transparent" }}>{children}</span>
  );

  // Card wrapper matching the CRM dossier left-column panels.
  function Panel({ title, badge, count, source, children }) {
    return (
      <section className="card" style={{ marginTop: 20 }}>
        <div className="card-head">
          <span className="ch-title">{title}</span>
          {badge}
          {count != null && <span className="pill" style={{ padding: "1px 7px" }}><span className="fact">{count}</span></span>}
          <span className="ch-spacer"></span>
          {source && <span className="src">{source}</span>}
        </div>
        {children}
      </section>
    );
  }
  // A reg-row inside a reg-panel: badge + title/fact + optional right.
  function RegRow({ badge, badgeBg, title, fact, right }) {
    return (
      <div className="reg-row">
        {badge != null && <span className="reg-badge" style={{ background: badgeBg || "var(--fg-3)" }}>{badge}</span>}
        <div className="reg-main"><div className="reg-title" style={{ whiteSpace: "normal" }}>{title}</div>{fact && <div className="reg-fact" style={{ whiteSpace: "normal" }}>{fact}</div>}</div>
        {right && <div className="reg-right"><span className="src" style={{ justifyContent: "flex-end" }}>{right}</span></div>}
      </div>
    );
  }
  // Label/value field row (mirrors the map's dsField).
  function Field({ l, v, mono }) {
    if (v == null || v === "") return null;
    return <div className="field"><span className="fl">{l}</span><span className="fv" style={mono ? { fontFamily: "var(--font-mono)", fontSize: "var(--fs-base)" } : null}>{v}</span></div>;
  }
  // Address block (DOS process-server / registered-agent / principal addresses).
  function AddrBlock({ label, address }) {
    if (!address) return null;
    return (
      <div style={{ marginTop: 8 }}>
        <div style={{ fontSize: "var(--fs-sm)", color: "var(--fg-3)", fontWeight: 600 }}>{label}</div>
        <div style={{ fontSize: "var(--fs-base)", color: "var(--fg-1)", whiteSpace: "pre-line", marginTop: 2 }}>{address}</div>
      </div>
    );
  }
  // Tiny footnote under a panel body.
  function Note({ children, color }) { return <div className="src" style={{ marginTop: 6, color: color || "var(--fg-3)", display: "block", whiteSpace: "normal" }}>{children}</div>; }

  const fmtAddr = (a1, a2, c, s, z) => {
    const line1 = [a1, a2].filter(Boolean).join(", ");
    const line2 = [c, [s, z].filter(Boolean).join(" ")].filter(Boolean).join(", ");
    return [line1, line2].filter(Boolean).join("\n");
  };

  window.CrmPanelKit = { usePanelData, rpcLoad, fnGet, money, num, fmtDate, fmtMonth, SrcBadge, Flag, Panel, RegRow, Field, AddrBlock, Note, fmtAddr };

  // ───────────────────────── PANELS ─────────────────────────

  // NY DOS filing — registered process server, county, formation date, dormancy.
  window.CrmPanels.dos = function DosFiling({ orgId }) {
    const rows = usePanelData(rpcLoad("org_dos_filing"), orgId);
    const row = Array.isArray(rows) ? rows[0] : rows;
    if (!row || !row.dos_id) return null;
    const procAddr = fmtAddr(row.dos_process_address_1, row.dos_process_address_2, row.dos_process_city, row.dos_process_state, row.dos_process_zip);
    const raAddr = fmtAddr(row.registered_agent_address_1, row.registered_agent_address_2, row.registered_agent_city, row.registered_agent_state, row.registered_agent_zip);
    const chAddr = fmtAddr(row.chairman_address_1, row.chairman_address_2, row.chairman_city, row.chairman_state, row.chairman_zip);
    const locAddr = fmtAddr(row.location_address_1, row.location_address_2, row.location_city, row.location_state, row.location_zip);
    const flags = [];
    if (row.entity_status) flags.push(<Flag key="s" bg="#dcfce7" color="#166534">{row.entity_status}</Flag>);
    if (row.is_dormant) flags.push(<Flag key="d" bg="#fee2e2" color="#991b1b" title={row.dormant_reason || ""}>{"Dormant" + (row.dormant_reason ? " · " + row.dormant_reason : "")}</Flag>);
    if (row.is_shell_cached) flags.push(<Flag key="sh" bg="#fef3c7" color="#92400e">Shell-LLC pattern</Flag>);
    if (row.statement_status === "PAST_DUE") flags.push(<Flag key="pd" bg="#fee2e2" color="#991b1b">Biennial past due</Flag>);
    return (
      <Panel title="NY DOS filing" badge={<SrcBadge bg="#ddd6fe" color="#5b21b6">DOS</SrcBadge>}>
        <div style={{ padding: "6px 16px 14px" }}>
          <Field l="Registered name" v={row.current_entity_name} mono />
          <Field l="Entity type" v={row.entity_type} />
          <Field l="County" v={row.county} />
          {row.jurisdiction && row.jurisdiction !== "NEW YORK" && <Field l="Jurisdiction" v={row.jurisdiction} />}
          <Field l="Filed" v={row.initial_dos_filing_date} />
          {flags.length > 0 && <Field l="Status" v={<span style={{ display: "inline-flex", gap: 4, flexWrap: "wrap" }}>{flags}</span>} />}
          <AddrBlock label={"Process server" + (row.dos_process_name ? " · " + row.dos_process_name : "")} address={procAddr} />
          <AddrBlock label={"Registered agent" + (row.registered_agent_name ? " · " + row.registered_agent_name : "")} address={raAddr} />
          <AddrBlock label={"Principal office" + (row.chairman_name ? " · " + row.chairman_name : "")} address={chAddr} />
          <AddrBlock label="Filing-listed location" address={locAddr} />
          <Note>DOS ID {row.dos_id}</Note>
        </div>
      </Panel>
    );
  };

  // FL Sunbiz filing — Florida's DOS-equivalent.
  window.CrmPanels.fldos = function FlDosFiling({ orgId }) {
    const rows = usePanelData(rpcLoad("org_fl_dos_filing"), orgId);
    const row = Array.isArray(rows) ? rows[0] : rows;
    if (!row || !row.doc_number) return null;
    const raAddr = fmtAddr(row.registered_agent_address_1, null, row.registered_agent_city, row.registered_agent_state, row.registered_agent_zip);
    const prinAddr = fmtAddr(row.principal_address_1, row.principal_address_2, row.principal_city, row.principal_state, row.principal_zip);
    const mailAddr = fmtAddr(row.mail_address_1, row.mail_address_2, row.mail_city, row.mail_state, row.mail_zip);
    const ftMap = { FLAL: "Domestic LLC", DOMP: "Domestic Profit Corp", DOMNP: "Domestic Non-Profit", FORL: "Foreign LLC", FORP: "Foreign Profit Corp", FORNP: "Foreign Non-Profit", DOMLP: "Domestic LP", FORLP: "Foreign LP", DOMGP: "Domestic General Partnership", TRUST: "Trust", NPREG: "Non-Profit Registration" };
    const flags = [];
    if (row.entity_status === "A") flags.push(<Flag key="a" bg="#dcfce7" color="#166534">Active</Flag>);
    else if (row.entity_status === "I") flags.push(<Flag key="i" bg="#fee2e2" color="#991b1b">Inactive</Flag>);
    else if (row.entity_status) flags.push(<Flag key="o" bg="#f1f5f9" color="#475569">{row.entity_status}</Flag>);
    if (row.officers_count > 0) flags.push(<Flag key="of" bg="#e0e7ff" color="#3730a3">{row.officers_count + " officer" + (row.officers_count > 1 ? "s" : "")}</Flag>);
    return (
      <Panel title="FL Sunbiz filing" badge={<SrcBadge bg="#ddd6fe" color="#5b21b6">DOS</SrcBadge>}>
        <div style={{ padding: "6px 16px 14px" }}>
          <Field l="Registered name" v={row.corporation_name} mono />
          <Field l="Entity type" v={row.filing_type ? (ftMap[row.filing_type] || row.filing_type) : null} />
          <Field l="FEI / EIN" v={row.fei_number} mono />
          {row.state_country && row.state_country !== "FL" && <Field l="Jurisdiction" v={row.state_country} />}
          <Field l="Filed" v={row.file_date} />
          <Field l="Last activity" v={row.last_transaction_date} />
          {flags.length > 0 && <Field l="Status" v={<span style={{ display: "inline-flex", gap: 4, flexWrap: "wrap" }}>{flags}</span>} />}
          <AddrBlock label={"Registered agent" + (row.registered_agent_name ? " · " + row.registered_agent_name : "")} address={raAddr} />
          <AddrBlock label="Principal address" address={prinAddr} />
          {mailAddr && mailAddr !== prinAddr && <AddrBlock label="Mailing address" address={mailAddr} />}
          <Note>Sunbiz Doc# {row.doc_number}</Note>
        </div>
      </Panel>
    );
  };

  // CT business registry — status, registered agent, principal & filing counts,
  // recent annual reports, diversity-ownership flags.
  window.CrmPanels.ctdos = function CtDosFiling({ orgId }) {
    const rows = usePanelData(rpcLoad("org_ct_dos_filing"), orgId);
    const row = Array.isArray(rows) ? rows[0] : rows;
    if (!row || !row.ct_id) return null;
    const agentAddr = [row.agent_address, [row.agent_city, [row.agent_state, row.agent_zip].filter(Boolean).join(" ")].filter(Boolean).join(", ")].filter(Boolean).join("\n");
    const flags = [];
    if (row.status === "Active") flags.push(<Flag key="a" bg="#dcfce7" color="#166534">Active</Flag>);
    else if (row.status) flags.push(<Flag key="s" bg="#fee2e2" color="#991b1b">{row.status}</Flag>);
    if (row.principal_count > 0) flags.push(<Flag key="p" bg="#e0e7ff" color="#3730a3">{row.principal_count + " principal" + (row.principal_count > 1 ? "s" : "")}</Flag>);
    if (row.filing_count > 0) flags.push(<Flag key="f" bg="#f1f5f9" color="#475569">{row.filing_count + " filing" + (row.filing_count > 1 ? "s" : "")}</Flag>);
    const div = [];
    if (row.woman_owned) div.push(<Flag key="w" bg="#fce7f3" color="#9d174d">Woman-owned</Flag>);
    if (row.veteran_owned) div.push(<Flag key="v" bg="#dbeafe" color="#1e40af">Veteran-owned</Flag>);
    if (row.minority_owned) div.push(<Flag key="m" bg="#fef3c7" color="#854d0e">Minority-owned</Flag>);
    if (row.disability_owned) div.push(<Flag key="d" bg="#e0f2fe" color="#075985">Disability-owned</Flag>);
    if (row.lgbtqi_owned) div.push(<Flag key="l" bg="#ede9fe" color="#5b21b6">LGBTQI-owned</Flag>);
    const recent = Array.isArray(row.recent_filings) ? row.recent_filings : [];
    return (
      <Panel title="CT business registry" badge={<SrcBadge bg="#ddd6fe" color="#5b21b6">DOS</SrcBadge>}>
        <div style={{ padding: "6px 16px 14px" }}>
          <Field l="Registered name" v={row.name} mono />
          <Field l="Account #" v={row.accountnumber} mono />
          {row.date_registration && !String(row.date_registration).startsWith("0001-") && <Field l="Registered" v={row.date_registration} />}
          {flags.length > 0 && <Field l="Status" v={<span style={{ display: "inline-flex", gap: 4, flexWrap: "wrap" }}>{flags}</span>} />}
          {div.length > 0 && <Field l="Designations" v={<span style={{ display: "inline-flex", gap: 4, flexWrap: "wrap" }}>{div}</span>} />}
          <AddrBlock label={"Registered agent" + (row.agent_name ? " · " + row.agent_name : "")} address={agentAddr} />
          {recent.length > 0 && (
            <div style={{ marginTop: 8 }}>
              <div style={{ fontSize: "var(--fs-sm)", color: "var(--fg-3)", fontWeight: 600, textTransform: "uppercase", letterSpacing: ".05em", marginBottom: 4 }}>Recent filings</div>
              {recent.map((f, i) => (
                <div key={i} style={{ display: "flex", gap: 8, fontSize: "var(--fs-base)", padding: "2px 0" }}>
                  <span style={{ color: "var(--fg-3)", minWidth: 90, fontFamily: "var(--font-mono)", fontSize: "var(--fs-sm)" }}>{f.date && !String(f.date).startsWith("0001-") ? f.date : ""}</span>
                  <span style={{ color: "var(--fg-1)", flex: 1 }}>{f.type || ""}</span>
                </div>
              ))}
            </div>
          )}
          <Note>CT business ID {row.ct_id}</Note>
        </div>
      </Panel>
    );
  };

  // CO Secretary of State — entity status/type, agent, tradenames (DBAs), transactions.
  window.CrmPanels.codos = function CoDosFiling({ orgId }) {
    const rows = usePanelData(rpcLoad("org_co_dos_filing"), orgId);
    const row = Array.isArray(rows) ? rows[0] : rows;
    if (!row || !row.co_id) return null;
    const etMap = { DLLC: "Domestic LLC", FLLC: "Foreign LLC", DPC: "Domestic Profit Corp", FPC: "Foreign Profit Corp", DNC: "Domestic Nonprofit", FNC: "Foreign Nonprofit", DLP: "Domestic LP", FLP: "Foreign LP", DLLP: "Domestic LLP", FLLP: "Foreign LLP", TRUST: "Trust" };
    const prinAddr = [row.principal_address1, [row.principal_city, [row.principal_state, row.principal_zipcode].filter(Boolean).join(" ")].filter(Boolean).join(", ")].filter(Boolean).join("\n");
    const agentAddr = [row.agent_address1, [row.agent_city, [row.agent_state, row.agent_zipcode].filter(Boolean).join(" ")].filter(Boolean).join(", ")].filter(Boolean).join("\n");
    const agentName = [row.agent_first_name, row.agent_last_name].filter(Boolean).join(" ").trim();
    const flags = [];
    if (row.entity_status === "Good Standing") flags.push(<Flag key="g" bg="#dcfce7" color="#166534">Good standing</Flag>);
    else if (row.entity_status === "Exists") flags.push(<Flag key="e" bg="#dcfce7" color="#166534">Exists</Flag>);
    else if (row.entity_status) flags.push(<Flag key="s" bg="#fee2e2" color="#991b1b">{row.entity_status}</Flag>);
    if (row.tradename_count > 0) flags.push(<Flag key="t" bg="#e0e7ff" color="#3730a3">{row.tradename_count + " DBA" + (row.tradename_count > 1 ? "s" : "")}</Flag>);
    if (row.transaction_count > 0) flags.push(<Flag key="x" bg="#f1f5f9" color="#475569">{row.transaction_count + " filing" + (row.transaction_count > 1 ? "s" : "")}</Flag>);
    const tradenames = Array.isArray(row.active_tradenames) ? row.active_tradenames : [];
    const txs = Array.isArray(row.recent_transactions) ? row.recent_transactions : [];
    const miniRow = (d, t, i) => (
      <div key={i} style={{ display: "flex", gap: 8, fontSize: "var(--fs-base)", padding: "2px 0" }}>
        <span style={{ color: "var(--fg-3)", minWidth: 90, fontFamily: "var(--font-mono)", fontSize: "var(--fs-sm)" }}>{d}</span>
        <span style={{ color: "var(--fg-1)", flex: 1 }}>{t}</span>
      </div>
    );
    return (
      <Panel title="CO Secretary of State" badge={<SrcBadge bg="#ddd6fe" color="#5b21b6">DOS</SrcBadge>}>
        <div style={{ padding: "6px 16px 14px" }}>
          <Field l="Registered name" v={row.name} mono />
          <Field l="Entity type" v={row.entity_type ? (etMap[row.entity_type] || row.entity_type) : null} />
          {row.jurisdiction_of_formation && row.jurisdiction_of_formation !== "CO" && <Field l="Jurisdiction" v={row.jurisdiction_of_formation} />}
          <Field l="Formed" v={row.entity_form_date} />
          {flags.length > 0 && <Field l="Status" v={<span style={{ display: "inline-flex", gap: 4, flexWrap: "wrap" }}>{flags}</span>} />}
          <AddrBlock label="Principal address" address={prinAddr} />
          <AddrBlock label={"Registered agent" + (agentName ? " · " + agentName : "")} address={agentAddr} />
          {tradenames.length > 0 && (
            <div style={{ marginTop: 8 }}>
              <div style={{ fontSize: "var(--fs-sm)", color: "var(--fg-3)", fontWeight: 600, textTransform: "uppercase", letterSpacing: ".05em", marginBottom: 4 }}>Active DBAs</div>
              {tradenames.map((t, i) => miniRow(t.effective ? String(t.effective).slice(0, 10) : "", t.name || "", i))}
            </div>
          )}
          {txs.length > 0 && (
            <div style={{ marginTop: 8 }}>
              <div style={{ fontSize: "var(--fs-sm)", color: "var(--fg-3)", fontWeight: 600, textTransform: "uppercase", letterSpacing: ".05em", marginBottom: 4 }}>Recent filings</div>
              {txs.map((tx, i) => miniRow(tx.date ? String(tx.date).slice(0, 10) : "", tx.description || "", i))}
            </div>
          )}
          <Note>CO entity ID {row.co_id}</Note>
        </div>
      </Panel>
    );
  };

  // Generic state business registry (AK/DC/IA/ND/PA/VA).
  window.CrmPanels.statedos = function StateDos({ orgId }) {
    const d = usePanelData(rpcLoad("org_state_dos_filing"), orgId);
    if (!d || !d.entity_name) return null;
    const STATE = { AK: "Alaska", DC: "District of Columbia", IA: "Iowa", ND: "North Dakota", PA: "Pennsylvania", VA: "Virginia" };
    const up = String(d.status || "").toUpperCase();
    const ok = up.includes("ACTIVE") || up.includes("GOOD") || up.includes("CURRENT");
    return (
      <Panel title={(STATE[d.state] || d.state) + " business registry"} badge={<SrcBadge bg="#ddd6fe" color="#5b21b6">DOS</SrcBadge>}>
        <div style={{ padding: "6px 16px 14px" }}>
          <Field l="Registered name" v={d.entity_name} mono />
          <Field l="Type" v={d.entity_type} />
          {d.status && <Field l="Status" v={<Flag bg={ok ? "#dcfce7" : "#fee2e2"} color={ok ? "#166534" : "#991b1b"}>{d.status}</Flag>} />}
          {d.formed_date && fmtDate(d.formed_date) && <Field l="Formed" v={fmtDate(d.formed_date)} />}
          <Field l="Address" v={d.address} />
          <Field l="Registered agent" v={d.agent} />
          <Field l="County" v={d.county} />
          <Note>{(STATE[d.state] || d.state)} SOS · entity {d.entity_id || ""}</Note>
        </div>
      </Panel>
    );
  };

  // OFAC / federal screening lists — confirmed (address-verified) vs review (namesake).
  window.CrmPanels.ofac = function Ofac({ orgId }) {
    const d = usePanelData(rpcLoad("org_ofac_screening"), orgId);
    if (!d || (!d.confirmed_count && !d.review_count)) return null;
    const mk = (e, confirmed, i) => {
      const progs = Array.isArray(e.programs) && e.programs.length ? " · " + e.programs.slice(0, 4).join(", ") : "";
      return (
        <RegRow key={(confirmed ? "c" : "r") + i}
          badge={confirmed ? "⛔" : "⚠"} badgeBg={confirmed ? "#991b1b" : "#854d0e"}
          title={e.name || ""}
          fact={(e.source_list || "") + (e.country ? " · " + e.country : "") + progs}
          right={confirmed ? "address-confirmed" : "name match"} />
      );
    };
    const conf = Array.isArray(d.confirmed) ? d.confirmed : [];
    const rev = Array.isArray(d.review) ? d.review : [];
    return (
      <Panel title="Screening lists" badge={<SrcBadge bg="#fee2e2" color="#991b1b">OFAC</SrcBadge>}>
        <div className="reg-panel">{conf.map((e, i) => mk(e, true, i))}{rev.map((e, i) => mk(e, false, i))}</div>
        <div style={{ padding: "0 14px 12px" }}>
          {d.confirmed_count
            ? <Note color="#991b1b">An address-confirmed match to a federal sanctions / denied-party list. Verify before any dealing.</Note>
            : <Note>A company on a federal screening list shares this name. This is an <b>unverified namesake</b> — most are unrelated foreign entities. Not an assertion that this company is sanctioned.</Note>}
        </div>
      </Panel>
    );
  };

  // FDA-registered establishments (medical-device makers / contract manufacturers).
  window.CrmPanels.fda = function Fda({ orgId }) {
    const d = usePanelData(rpcLoad("org_fda_establishments"), orgId);
    if (!d || !d.count) return null;
    const facs = Array.isArray(d.establishments) ? d.establishments : [];
    return (
      <Panel title="FDA establishments" badge={<SrcBadge bg="#dbeafe" color="#1e40af">FDA</SrcBadge>} count={d.count}>
        <div className="reg-panel">
          {facs.map((f, i) => {
            const addr = [f.street, f.city, f.state, f.zip].filter(Boolean).join(", ");
            const parent = f.firm_name && f.firm_name.toUpperCase() !== (f.name || "").toUpperCase() ? " (owner: " + f.firm_name + ")" : "";
            const types = Array.isArray(f.establishment_types) && f.establishment_types.length ? f.establishment_types.slice(0, 3).join(" · ") : "";
            return <RegRow key={i} badge={f.device_count ? f.device_count : "FDA"} badgeBg="#1e40af"
              title={(f.name || "") + parent}
              fact={[addr, f.reg_expiry_year ? "reg " + f.reg_expiry_year : null, types].filter(Boolean).join(" · ")} />;
          })}
        </div>
        <div style={{ padding: "0 14px 12px" }}><Note>FDA medical-device establishment registrations (openFDA).</Note></div>
      </Panel>
    );
  };

  // EPA Toxic Release Inventory facilities.
  window.CrmPanels.tri = function Tri({ orgId }) {
    const d = usePanelData(rpcLoad("org_epa_tri"), orgId);
    if (!d || !d.count) return null;
    const facs = Array.isArray(d.facilities) ? d.facilities : [];
    return (
      <Panel title="EPA TRI facilities" badge={<SrcBadge bg="#dcfce7" color="#166534">EPA</SrcBadge>}
        count={d.active_count != null ? d.count + " · " + d.active_count + " active" : d.count}>
        <div className="reg-panel">
          {facs.map((f, i) => {
            const addr = [f.street, f.city, f.county ? f.county + " Co." : "", f.state, f.zip].filter(Boolean).join(", ");
            const parent = f.parent_co_name ? "Parent: " + (f.standardized_parent_company || f.parent_co_name) : "";
            return <RegRow key={i} badge={f.fac_closed ? "✕" : "TRI"} badgeBg={f.fac_closed ? "#64748b" : "#166534"}
              title={f.facility_name || ""} fact={[addr, parent].filter(Boolean).join(" · ")} />;
          })}
        </div>
        <div style={{ padding: "0 14px 12px" }}><Note>Facilities reporting to the EPA Toxic Release Inventory.</Note></div>
      </Panel>
    );
  };

  // NPPES (CMS NPI registry) — healthcare provider registration (live edge fn).
  window.CrmPanels.nppes = function Nppes({ orgId }) {
    const d = usePanelData(fnGet("/functions/v1/enrich-nppes"), orgId);
    if (!d || !d.count) return null;
    const provs = Array.isArray(d.providers) ? d.providers : [];
    return (
      <Panel title="Healthcare provider (NPI)" badge={<SrcBadge bg="#cffafe" color="#155e75">NPPES</SrcBadge>}>
        <div className="reg-panel">
          {provs.map((p, i) => {
            const addr = [p.street, p.city, p.state, p.zip].filter(Boolean).join(", ");
            const ao = p.auth_official_name ? "Authorized official: " + p.auth_official_name + (p.auth_official_title ? ", " + p.auth_official_title : "") + (p.auth_official_phone ? " · " + p.auth_official_phone : "") : "";
            return <RegRow key={i} badge="NPI" badgeBg="#155e75"
              title={p.organization_name || p.person_name || ""}
              fact={<>{[addr, "NPI " + p.npi, p.license ? "lic " + p.license : null].filter(Boolean).join(" · ")}{ao && <div style={{ marginTop: 2 }}>{ao}</div>}{p.primary_taxonomy_desc && <div style={{ marginTop: 2 }}>{p.primary_taxonomy_desc}</div>}</>} />;
          })}
        </div>
        <div style={{ padding: "0 14px 12px" }}><Note>CMS National Provider Identifier registration (NPPES). The authorized official is a verified human contact.</Note></div>
      </Panel>
    );
  };

  // FollowTheMoney — state/local campaign contributions made by this company.
  window.CrmPanels.ftm = function Ftm({ orgId }) {
    const d = usePanelData(rpcLoad("org_ftm_contributions"), orgId);
    if (!d || !d.matched || !(Number(d.total_amount) > 0)) return null;
    const amt = Number(d.total_amount);
    const yrs = Array.isArray(d.years) ? d.years.filter(Boolean).sort() : [];
    return (
      <Panel title="State political giving" badge={<SrcBadge bg="#dcfce7" color="#166534">FTM</SrcBadge>}>
        <div style={{ padding: "12px 16px 14px" }}>
          <div>
            <Flag bg="#dcfce7" color="#166534"><span style={{ fontSize: 13, fontWeight: 700 }}>${amt.toLocaleString(undefined, { maximumFractionDigits: 0 })}</span></Flag>
            <span style={{ fontSize: "var(--fs-sm)", color: "var(--fg-3)", marginLeft: 6 }}>in state/local campaign contributions</span>
          </div>
          {yrs.length > 0 && <Note>{yrs[0]}{yrs.length > 1 ? "–" + yrs[yrs.length - 1] : ""} · {d.count || ""} contribution{d.count === 1 ? "" : "s"}</Note>}
          <Note>FollowTheMoney (National Institute on Money in Politics) — state &amp; local campaign finance.</Note>
        </div>
      </Panel>
    );
  };

  // USPTO patents — granted + applications (stored counts, live titles).
  window.CrmPanels.patents = function Patents({ orgId }) {
    const d = usePanelData(rpcLoad("org_patents_stored"), orgId);
    const [recent, setRecent] = useState([]);
    const granted = d && d.granted_count ? Number(d.granted_count) : 0;
    const apps = d && d.application_count ? Number(d.application_count) : 0;
    useEffect(() => {
      const stored = (d && Array.isArray(d.recent)) ? d.recent : [];
      if (stored.length) { setRecent(stored); return; }
      if (!(granted > 0 || apps > 0) || !orgId) { setRecent([]); return; }
      let alive = true;
      const base = (window.ContactIQ && window.ContactIQ.SUPABASE_URL) || "";
      const key = (window.ContactIQ && window.ContactIQ.SUPABASE_KEY) || "";
      fetch(base + "/functions/v1/enrich-uspto-patents?org_id=" + orgId, { headers: { apikey: key, Authorization: "Bearer " + key } })
        .then((r) => r.json()).then((e) => { if (alive && e && Array.isArray(e.recent)) setRecent(e.recent); }).catch(() => {});
      return () => { alive = false; };
    }, [d, orgId]);
    if (d === undefined) return null;
    if (!granted && !apps && recent.length === 0) return null;
    return (
      <Panel title="Patents" badge={<SrcBadge bg="#fef3c7" color="#92400e">USPTO</SrcBadge>}>
        <div style={{ padding: "10px 16px 0", display: "flex", gap: 6, flexWrap: "wrap" }}>
          {granted > 0 && <Flag bg="#fef3c7" color="#92400e">{granted.toLocaleString()} granted patent{granted === 1 ? "" : "s"} ’18–’24</Flag>}
          {apps > 0 && <Flag bg="#fffbeb" color="#92400e">{apps.toLocaleString()} application{apps === 1 ? "" : "s"}</Flag>}
        </div>
        <div className="reg-panel">
          {recent.map((p, i) => (
            <RegRow key={i} badge={p.type || "PAT"} badgeBg="#92400e"
              title={p.title || p.app_number || "—"}
              fact={[p.filing_date ? "Filed " + fmtMonth(p.filing_date) : null, p.status, p.pub_number].filter(Boolean).join(" · ")} />
          ))}
        </div>
        <div style={{ padding: "0 14px 12px" }}><Note>Granted counts from USPTO PatentsView bulk data; application titles from the USPTO Open Data Portal.</Note></div>
      </Panel>
    );
  };

  // FFIEC NIC — bank / holding-company ownership hierarchy.
  window.CrmPanels.nic = function Nic({ orgId }) {
    const d = usePanelData(rpcLoad("org_nic_hierarchy"), orgId);
    if (!d || !d.count) return null;
    const ents = Array.isArray(d.entities) ? d.entities : [];
    const pctTxt = (v) => (v != null && v !== "" ? " · " + Number(v).toFixed(Number(v) % 1 ? 1 : 0) + "%" : "");
    const ctrlTxt = (v) => (v === "Y" || v === "1" ? " · control" : "");
    const relRow = (r, i) => (
      <div key={i} style={{ fontSize: "var(--fs-sm)", color: "var(--fg-2)", marginLeft: 10 }}>
        {r.active === false && <span style={{ opacity: 0.6 }}>(former) </span>}{r.name || r.id_rssd}{pctTxt(r.pct_equity)}{ctrlTxt(r.control)}
      </div>
    );
    return (
      <Panel title="Bank ownership (NIC)" badge={<SrcBadge bg="#ede9fe" color="#5b21b6">FFIEC</SrcBadge>}>
        <div className="reg-panel">
          {ents.map((e, i) => {
            const ids = [e.id_fdic_cert ? "FDIC#" + e.id_fdic_cert : "", e.id_lei ? "LEI " + e.id_lei : ""].filter(Boolean).join(" · ");
            const parents = e.parents || [], kids = e.offspring || [];
            return (
              <div className="reg-row" key={i} style={{ alignItems: "flex-start" }}>
                <div className="reg-main">
                  <div className="reg-title" style={{ whiteSpace: "normal" }}>{e.name || ""} <span style={{ color: "var(--fg-3)", fontSize: 10, fontWeight: 400 }}>{e.regulator || e.entity_type || ""}</span></div>
                  <div style={{ fontSize: 10, color: "var(--fg-3)", fontFamily: "var(--font-mono)" }}>RSSD {e.id_rssd}{ids ? " · " + ids : ""}</div>
                  {parents.length > 0 && <div style={{ fontSize: "var(--fs-sm)", color: "var(--fg-1)", marginTop: 4 }}>Owned by:</div>}
                  {parents.slice(0, 12).map(relRow)}
                  {kids.length > 0 && <div style={{ fontSize: "var(--fs-sm)", color: "var(--fg-1)", marginTop: 4 }}>Owns {kids.length}:</div>}
                  {kids.slice(0, 12).map(relRow)}
                  {kids.length > 12 && <div style={{ fontSize: 10, color: "var(--fg-3)", marginLeft: 10 }}>+{kids.length - 12} more</div>}
                </div>
              </div>
            );
          })}
        </div>
        <div style={{ padding: "0 14px 12px" }}><Note>FFIEC National Information Center bank/holding-company structure.</Note></div>
      </Panel>
    );
  };
})();
