/* global React, Icon, Button, Avatar, AgentAvatar, Panel, SectionLabel, AgentNote, Segmented, TONES, NetworkMapGraph, SuperConnectorRail, RailHandle, MAP_COMPANIES, COMPANY_CLUSTERS, PERSON_CLUSTERS, MAP_CLUSTERS, MAP_CONNECTORS, MAP_UPDATED, MAP_STATS, PERSONA_DEFS, personasFor, primaryOf, makeDraft, INTRO_STEPS, DIRECT_STEPS, NET_THREADS, DetailPanel, ComposeModal, OutreachDrawer, UpsellModal, SyncOverlay */
// ============================================================
// Get introduced — ONE unified, filterable network map. Replaces the old
// per-company / per-person split. You → introducers → targets, with company
// clusters that expand in-graph, a super-connector ranking rail, type
// filter, zoom, and a "last updated / refresh" affordance (it's a
// precomputed aggregation, not a per-open spinner). No route changes.
// ============================================================
const { useState: useNet, useEffect: useNetEff } = React;

function ScrNetwork({ target, tier = "premium", strength = "strong", spotlight = false }) {
  const locked = tier === "free";
  const weak = strength === "weak";

  const [typeF, setTypeF] = useNet("both");
  const [expanded, setExpanded] = useNet(null);
  const [sel, setSel] = useNet(null);          // { persona, def } -> detail panel
  const [compose, setCompose] = useNet(null);
  const [drawer, setDrawer] = useNet(false);
  const [upsell, setUpsell] = useNet(false);
  const [focusId, setFocusId] = useNet(null);  // rail-driven introducer focus
  const [zoom, setZoom] = useNet(1);
  const [pan, setPan] = useNet({ x: 0, y: 0 });
  const [railOpen, setRailOpen] = useNet(true);
  const [threads, setThreads] = useNet(NET_THREADS);
  const [toast, setToast] = useNet(null);
  const [synced, setSynced] = useNet(true);
  const [resync, setResync] = useNet(false);
  const [updated, setUpdated] = useNet(MAP_UPDATED);
  const [refreshing, setRefreshing] = useNet(false);

  // Deep-link from a way-in badge / tracker Paths action: focus + open a cluster.
  useNetEff(() => {
    if (!target) return;
    const c = target.companyId && MAP_COMPANIES.find(x => x.id === target.companyId);
    if (c) { setTypeF("both"); setExpanded(c.id); setFocusId(c.via !== "direct" ? c.via : null); }
  }, [target]);

  const clusters = typeF === "people" ? PERSON_CLUSTERS : typeF === "companies" ? COMPANY_CLUSTERS : MAP_CLUSTERS;
  const visConnectors = MAP_CONNECTORS.filter(c => clusters.some(x => x.via === c.id));
  const expandedId = typeF === "people" ? null : expanded;
  const replyWaiting = threads.some(t => t.next && t.next.toLowerCase().includes("reply"));

  const openPerson = (persona, def) => { if (locked) { setUpsell(true); return; } setSel({ persona, def }); };
  const onCompose = (persona, def) => { setSel(null); setCompose({ persona, def }); };

  const onApprove = (persona, def) => {
    const path = primaryOf(persona), direct = path.degree === 1 || !path.score;
    setThreads(ts => [{
      id: "new-" + Date.now(), kind: direct ? "direct" : "intro", statusIndex: 0,
      target: path.target, introducer: path.introducer || { name: path.bridge || "a contact" },
      job: path.target.co ? `Reaching ${path.target.co}` : "Reaching out", updated: "just now",
      next: direct ? "Sent, awaiting reply" : `Awaiting ${(path.introducer ? path.introducer.name : path.bridge || "intro").split(" ")[0]}`,
      steps: direct ? DIRECT_STEPS : INTRO_STEPS, score: path.score,
      timeline: [{ who: "agent", label: direct ? "Offerroom sent your message" : "Offerroom sent the intro request", time: "just now" }],
    }, ...ts]);
    setCompose(null);
    setToast({ name: path.target.name.split(" ")[0], direct });
    setTimeout(() => setToast(null), 4000);
  };

  const draftForConnector = (c) => {
    if (locked) { setUpsell(true); return; }
    if (c.people && c.people.length) { setCompose({ persona: c.people[0].person.path, def: null }); return; }
    const co = c.companies[0]; if (!co) return;
    setCompose({ persona: personasFor(co).hm, def: PERSONA_DEFS[0] });
  };

  const refresh = () => {
    if (refreshing) return;
    setRefreshing(true);
    setTimeout(() => { setRefreshing(false); setUpdated("just now"); }, 1300);
  };

  const overlayOpen = sel || drawer;

  return (
    <div data-screen-label="Network map" style={{ display: "flex", flexDirection: "column", height: "100%", minHeight: 540, background: "var(--paper)", borderRadius: 14, border: "1px solid var(--ink-100)", overflow: "hidden", boxShadow: "var(--shadow-resting)", position: "relative" }}>

      {/* ---- Header: context + last-updated/refresh + filter + zoom + outreach ---- */}
      <div style={{ flexShrink: 0, borderBottom: "1px solid var(--ink-100)", background: "rgba(255,255,255,0.75)", backdropFilter: "blur(8px)", display: "flex", alignItems: "center", gap: 14, padding: "11px 16px", flexWrap: "wrap", zIndex: 16 }}>
        <span style={{ width: 30, height: 30, borderRadius: 8, background: "var(--cardinal-50)", color: "var(--cardinal)", display: "grid", placeItems: "center", flexShrink: 0 }}><Icon name="route" size={16}/></span>
        <div style={{ minWidth: 0 }}>
          <div style={{ fontSize: 13.5, fontWeight: 600, lineHeight: 1.15 }}>The warmest way into all your targets</div>
          <div style={{ fontSize: 11.5, color: "var(--fg-2)", display: "flex", alignItems: "center", gap: 8 }}>
            <span>{MAP_STATS.companies} companies · {MAP_STATS.people} people</span>
            <span style={{ width: 3, height: 3, borderRadius: 999, background: "var(--ink-300)" }}/>
            <button onClick={refresh} title="Re-aggregate paths" style={{ display: "inline-flex", alignItems: "center", gap: 5, background: "none", border: "none", cursor: "pointer", color: "var(--fg-2)", fontFamily: "var(--font-sans)", fontSize: 11.5, padding: 0 }}>
              <Icon name="refresh" size={12} style={{ animation: refreshing ? "cad-spin 0.9s linear infinite" : "none" }}/>
              {refreshing ? "Updating…" : `Updated ${updated}`}
            </button>
          </div>
        </div>

        <span style={{ flex: 1, minWidth: 12 }}/>

        <Segmented value={typeF} onChange={(v) => { setTypeF(v); setFocusId(null); }}
          options={[{ value: "both", label: "Both" }, { value: "companies", label: "Companies" }, { value: "people", label: "People" }]}/>

        <div style={{ display: "flex", alignItems: "center", gap: 2, background: "var(--paper-sunken)", border: "1px solid var(--ink-100)", borderRadius: 8, padding: 3 }}>
          <ZoomBtn icon="close" rotate label="Zoom out" onClick={() => setZoom(z => Math.max(0.55, +(z - 0.15).toFixed(2)))} mono="−"/>
          <button onClick={() => { setZoom(1); setPan({ x: 0, y: 0 }); }} title="Reset view" style={{ minWidth: 44, textAlign: "center", fontFamily: "var(--font-mono)", fontSize: 11.5, color: "var(--fg-2)", background: "none", border: "none", cursor: "pointer", padding: "2px 4px" }}>{Math.round(zoom * 100)}%</button>
          <ZoomBtn mono="+" label="Zoom in" onClick={() => setZoom(z => Math.min(2.0, +(z + 0.15).toFixed(2)))}/>
        </div>

        <button onClick={() => setDrawer(true)} style={{ display: "inline-flex", alignItems: "center", gap: 8, padding: "7px 13px", borderRadius: 8, border: "1px solid var(--ink-100)", background: "#fff", cursor: "pointer", fontFamily: "var(--font-sans)", fontSize: 12.5, fontWeight: 600, color: "var(--fg-1)" }}>
          <Icon name="inbox" size={15} style={{ color: "var(--fg-2)" }}/>Outreach
          <span style={{ fontSize: 11, color: "var(--fg-2)", fontFamily: "var(--font-mono)" }}>{threads.length}</span>
          {replyWaiting && <span style={{ width: 7, height: 7, borderRadius: 999, background: "var(--cardinal)" }}/>}
        </button>
      </div>

      {/* ---- Body: graph + super-connector rail ---- */}
      <div style={{ flex: 1, display: "flex", minHeight: 0 }}>
        <div style={{ flex: 1, position: "relative", minWidth: 0, overflow: "hidden", background: "radial-gradient(circle at 1px 1px, rgba(31,27,22,0.06) 1px, transparent 0) 0 0 / 24px 24px" }}>
          {weak ? (
            <SparseMap onSync={() => { setResync(false); setSynced(false); }}/>
          ) : (
            <NetworkMapGraph
              clusters={clusters} connectors={visConnectors}
              expandedId={expandedId} onToggleCluster={setExpanded}
              onOpenPerson={openPerson}
              focusId={focusId} onFocusIntro={setFocusId}
              locked={locked} spotlightId={spotlight ? (MAP_CONNECTORS[0] && MAP_CONNECTORS[0].id) : null}
              zoom={zoom} pan={pan} onZoom={setZoom} onPan={setPan}/>
          )}

          {!weak && !railOpen && !overlayOpen && <RailHandle onOpen={() => setRailOpen(true)} count={MAP_STATS.connectors}/>}
          {refreshing && <RefreshOverlay/>}

          {sel && <DetailPanel persona={sel.persona} def={sel.def} locked={false} onClose={() => setSel(null)} onCompose={onCompose} onUpsell={() => { setSel(null); setUpsell(true); }}/>}
          {drawer && <OutreachDrawer threads={threads} onClose={() => setDrawer(false)}/>}
          {toast && <Toast toast={toast} onView={() => { setToast(null); setDrawer(true); }}/>}
        </div>

        {!weak && railOpen && (
          <SuperConnectorRail connectors={MAP_CONNECTORS} focusId={focusId} onFocus={setFocusId}
            onDraft={draftForConnector} onClose={() => setRailOpen(false)} locked={locked} onUpsell={() => setUpsell(true)}/>
        )}
      </div>

      {!synced && <SyncOverlay firstRun={!resync} accountsSynced={resync} onDone={() => { setSynced(true); setResync(false); }}/>}
      {compose && <ComposeModal persona={compose.persona} def={compose.def} onClose={() => setCompose(null)} onApprove={onApprove}/>}
      {upsell && <UpsellModal onClose={() => setUpsell(false)}/>}
    </div>
  );
}

const ZoomBtn = ({ mono, label, onClick }) => (
  <button onClick={onClick} title={label} style={{ width: 26, height: 24, borderRadius: 6, border: "none", background: "#fff", cursor: "pointer", display: "grid", placeItems: "center", fontFamily: "var(--font-mono)", fontSize: 15, fontWeight: 600, color: "var(--fg-1)", boxShadow: "0 1px 1px rgba(31,27,22,0.05)" }}>{mono}</button>
);

// ---- Refresh / re-aggregation cue (not a per-open spinner) ----
const RefreshOverlay = () => (
  <div className="cad-fade" style={{ position: "absolute", left: "50%", top: 16, transform: "translateX(-50%)", zIndex: 20, display: "flex", alignItems: "center", gap: 10, padding: "9px 15px", background: "#fff", border: "1px solid var(--ink-100)", borderRadius: 999, boxShadow: "var(--shadow-floating)" }}>
    <span className="cad-pulse-dot"/>
    <span style={{ fontSize: 12.5, color: "var(--fg-1)" }}>Re-aggregating paths across your targets…</span>
  </div>
);

// ---- Sparse / empty map (case H5): too few paths to be useful ----
const SparseMap = ({ onSync }) => (
  <div style={{ position: "absolute", inset: 0, display: "grid", placeItems: "center", padding: 24 }}>
    <div style={{ position: "absolute", inset: 0, opacity: 0.5, pointerEvents: "none", display: "grid", placeItems: "center" }}>
      <svg width="320" height="220" style={{ maxWidth: "70%" }}>
        <line x1="160" y1="110" x2="80" y2="70" stroke="var(--ink-100)" strokeWidth="2"/>
        <line x1="160" y1="110" x2="250" y2="150" stroke="var(--ink-100)" strokeWidth="2"/>
        <circle cx="160" cy="110" r="9" fill="var(--ink-100)"/>
        <circle cx="80" cy="70" r="6" fill="var(--ink-100)"/>
        <circle cx="250" cy="150" r="6" fill="var(--ink-100)"/>
      </svg>
    </div>
    <Panel pad={0} style={{ width: 460, maxWidth: "100%", position: "relative", overflow: "hidden" }}>
      <div style={{ padding: "16px 18px" }}>
        <AgentNote time="now">Your map is still thin. I can reach a couple of your targets, but not enough to find a super-connector yet. Widen your network and I'll re-map it.</AgentNote>
      </div>
      <div style={{ padding: "0 18px 18px", display: "grid", gridTemplateColumns: "1fr 1fr", gap: 10 }}>
        <SparseCta icon="link" title="Sync another account" sub="Gmail or a second LinkedIn widens reach fast." cta="Connect" onClick={onSync}/>
        <SparseCta icon="userPlus" title="Invite a few people" sub="3 former colleagues can open dozens of doors." cta="Invite"/>
      </div>
    </Panel>
  </div>
);

const SparseCta = ({ icon, title, sub, cta, onClick }) => (
  <div style={{ border: "1px solid var(--ink-100)", borderRadius: 10, padding: 13, display: "flex", flexDirection: "column", gap: 8 }}>
    <span style={{ width: 30, height: 30, borderRadius: 8, background: "var(--paper-sunken)", display: "grid", placeItems: "center", color: "var(--fg-1)" }}><Icon name={icon} size={15}/></span>
    <div style={{ fontSize: 13, fontWeight: 600 }}>{title}</div>
    <div style={{ fontSize: 11.5, color: "var(--fg-2)", lineHeight: 1.45, flex: 1 }}>{sub}</div>
    <Button variant="secondary" size="sm" icon="arrow" onClick={onClick}>{cta}</Button>
  </div>
);

// ---- Outreach confirmation toast ----
function Toast({ toast, onView }) {
  return (
    <div className="cad-rise" style={{ position: "absolute", left: "50%", bottom: 22, transform: "translateX(-50%)", zIndex: 35, display: "flex", alignItems: "center", gap: 12, padding: "11px 13px 11px 15px", background: "#1F1B16", color: "#F6F4EF", borderRadius: 999, boxShadow: "0 12px 32px rgba(31,27,22,0.28)" }}>
      <span style={{ width: 7, height: 7, borderRadius: 999, background: "#5A7150" }}/>
      <span style={{ fontSize: 13 }}>{toast.direct ? `Message to ${toast.name} sent.` : "Intro requested. Tracking it for you."}</span>
      <button onClick={onView} style={{ fontSize: 12.5, fontWeight: 600, color: "#F6F4EF", background: "rgba(255,255,255,0.14)", border: "none", borderRadius: 999, padding: "4px 11px", cursor: "pointer", fontFamily: "var(--font-sans)" }}>View</button>
    </div>
  );
}

window.ScrNetwork = ScrNetwork;
