/* App shell — top nav, tab routing, state, tweaks. */
const { useState: useStateApp, useEffect: useEffectApp } = React;
const { TOKENS: T_APP, useViewport: useViewportApp } = window.IE_UI;
const { Intake } = window.IE_INTAKE;
const { Diagnostic } = window.IE_DIAGNOSTIC;
const { Brief } = window.IE_BRIEF;
const ENGINE = window.IE_ENGINE;

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "density": "comfortable",
  "briefLayout": "left-nav",
  "showInternalSections": true
}/*EDITMODE-END*/;

function buildState(intake) {
  const diag = ENGINE.runDiagnostic(intake);
  return {
    intake,
    diag,
    tl: ENGINE.thesisLine(intake),
    th: ENGINE.thesis(intake),
    arch: ENGINE.archetypes(intake),
    rsk: ENGINE.risks(intake, diag),
    asm: ENGINE.assumptions(intake),
    plan: ENGINE.operatingPlan(),
    stake: ENGINE.stakeholderNotes(intake),
    stops: ENGINE.stopConditions(intake, diag),
    plays: ENGINE.outreachPlays(intake),
  };
}

/* ------------- TOP NAV ------------- */
function TopBar({ tab, setTab, density }) {
  const { isMobile } = useViewportApp();
  const tabs = [
    { id: "intake", label: "Intake", num: "01" },
    { id: "diagnostic", label: "Diagnostic", num: "02" },
    { id: "brief", label: "Intel Brief", num: "03" },
    { id: "export", label: "Export", num: "04" },
  ];
  return (
    <header style={{
      position: "sticky", top: 0, zIndex: 50,
      background: "rgba(11,13,17,.92)", backdropFilter: "blur(10px)",
      borderBottom: `1px solid ${T_APP.border}`,
    }}>
      <div style={{
        display: "flex", flexDirection: isMobile ? "column" : "row",
        justifyContent: "space-between", alignItems: isMobile ? "stretch" : "center",
        gap: isMobile ? 8 : 0,
        padding: isMobile ? "10px 16px" : (density === "compact" ? "10px 28px" : "14px 32px"),
        maxWidth: 1320, margin: "0 auto",
      }}>
        <div style={{ display: "flex", alignItems: "center", gap: 14 }}>
          <div style={{
            width: 26, height: 26, borderRadius: 4,
            background: `linear-gradient(135deg, ${T_APP.amber} 0%, ${T_APP.amberDim} 100%)`,
            display: "flex", alignItems: "center", justifyContent: "center",
            fontFamily: T_APP.mono, fontSize: 13, fontWeight: 800, color: "#1a1a1a",
            letterSpacing: "-0.02em", flexShrink: 0,
          }}>IE</div>
          <div>
            <div style={{ font: `600 14px/1 ${T_APP.sans}`, color: T_APP.text, letterSpacing: "-0.01em" }}>
              Intel Engine
            </div>
            {!isMobile && (
              <div style={{ fontFamily: T_APP.mono, fontSize: 9.5, color: T_APP.muted, letterSpacing: ".08em", textTransform: "uppercase", marginTop: 1 }}>
                v0.1 · Session 1
              </div>
            )}
          </div>
        </div>

        <nav style={{
          display: "flex", gap: isMobile ? 0 : 2,
          overflowX: isMobile ? "auto" : "visible",
          margin: isMobile ? "0 -16px" : 0,
          padding: isMobile ? "0 16px" : 0,
          scrollbarWidth: "none",
          WebkitOverflowScrolling: "touch",
        }}>
          {tabs.map(t => {
            const active = tab === t.id;
            return (
              <button key={t.id} onClick={() => setTab(t.id)} style={{
                background: active ? T_APP.panel2 : "transparent",
                border: "none",
                color: active ? T_APP.text : T_APP.muted,
                padding: isMobile ? "8px 12px" : "8px 14px",
                borderRadius: 4, cursor: "pointer",
                fontFamily: T_APP.sans, fontSize: isMobile ? 12 : 12.5, fontWeight: active ? 600 : 500,
                display: "flex", alignItems: "baseline", gap: 7,
                transition: "color .12s, background .12s",
                flexShrink: 0, whiteSpace: "nowrap",
              }}
                onMouseEnter={(e) => { if (!active) e.currentTarget.style.color = T_APP.text; }}
                onMouseLeave={(e) => { if (!active) e.currentTarget.style.color = T_APP.muted; }}
              >
                <span style={{ fontFamily: T_APP.mono, fontSize: 9.5, color: active ? T_APP.amber : T_APP.mutedDeep }}>{t.num}</span>
                {t.label}
              </button>
            );
          })}
        </nav>

        {!isMobile && (
          <div style={{ display: "flex", alignItems: "center", gap: 14 }}>
            <div style={{ fontFamily: T_APP.mono, fontSize: 10, color: T_APP.muted, letterSpacing: ".06em" }}>
              <span style={{ color: T_APP.amber }}>●</span> Direction frozen
            </div>
          </div>
        )}
      </div>
    </header>
  );
}

/* ------------- EXPORT TAB ------------- */
function buildMarkdown(state, surface) {
  const { intake: i, diag, tl, th, arch, rsk, asm, plan, stake, stops, plays } = state;
  const isInternal = surface === "internal";
  const role = i.role_title || i.role_family;
  const company = i.company || "[Company]";
  const lines = [];
  lines.push(`# Intel Brief — ${role} @ ${company}`, "");
  lines.push(`*${i.industry || "[industry]"} · ${i.ownership} · ${i.stage} · ${i.tier} tier*`, "");

  lines.push(`## Diagnostic`, "");
  lines.push(`**Score: ${diag.score}/5** — ${diag.msg}`, "");
  if (isInternal) {
    diag.gates.forEach((g, idx) => {
      lines.push(`- **Gate ${idx+1} ${g.yes?"✓":"✗"}** ${g.q}`);
      lines.push(`  - ${g.reason}`);
      if (g.intervention) lines.push(`  - *Intervention:* ${g.intervention}`);
    });
    lines.push("");
  }

  lines.push(`## Thesis Line`, "", `> ${tl}`, "");
  lines.push(`## Search Thesis`, "", th, "");

  lines.push(`## Company & Role Context`, "");
  lines.push(`**${company}** — ${i.industry || "[industry]"}, ${i.ownership}, ${i.stage}.`);
  if (i.company_events) lines.push("", i.company_events);
  lines.push("");
  if (i.mandate) lines.push(`**Mandate:** ${i.mandate}`, "");
  if (i.must_haves.length) {
    lines.push("**Must-haves:**");
    i.must_haves.forEach(m => lines.push(`- ${m}`));
    lines.push("");
  }

  lines.push(`## Market State Map`, "");
  if (i.market.length) {
    lines.push(`| Tier | Company | State | Reason | Source |`);
    lines.push(`|---|---|---|---|---|`);
    i.market.forEach(m => lines.push(`| ${m.tier} | ${m.company} | ${m.state} | ${m.reason || "requires validation"} | ${m.classification} |`));
  }
  if (i.off_limits.length) lines.push("", `**Off-limits:** ${i.off_limits.join(", ")}`);
  lines.push("");

  lines.push(`## Candidate Archetypes`, "");
  arch.forEach(a => {
    lines.push(`### ${a.name}  *(${a.confidence})*`);
    lines.push(a.desc);
    lines.push(`*Where to find:* ${a.where}`, "");
  });

  lines.push(`## Risks`, "");
  lines.push(`| Risk | Severity | Impact | Mitigation |`);
  lines.push(`|---|---|---|---|`);
  rsk.forEach(r => lines.push(`| ${r.risk} | ${r.severity} | ${r.impact} | ${r.mitigation} |`));
  lines.push("");

  lines.push(`## Assumptions to Validate`, "");
  if (asm.length) {
    lines.push(`| Assumption | Why | Validate | Owner |`);
    lines.push(`|---|---|---|---|`);
    asm.forEach(a => lines.push(`| ${a.assumption} | ${a.why} | ${a.validate} | ${a.owner} |`));
  }
  lines.push("");

  lines.push(`## 10-Day Operating Plan${isInternal ? " (with go/no-go gates)" : ""}`, "");
  plan.forEach(p => {
    lines.push(`**Day ${p.day} — ${p.action}**`);
    lines.push(`Owner: ${p.owner} · Output: ${p.output}`);
    if (isInternal) lines.push(`*Gate:* ${p.gate}`);
    lines.push("");
  });

  if (isInternal) {
    if (stake.length) {
      lines.push(`## Stakeholder Notes *(internal)*`, "");
      stake.forEach(s => lines.push(`**${s.kind}:** ${s.body}`, ""));
    }
    lines.push(`## Stop Conditions *(internal)*`, "");
    stops.forEach(s => lines.push(`- ${s}`));
    lines.push("");
    lines.push(`## Outreach Plays *(internal)*`, "");
    plays.forEach(p => {
      lines.push(`**${p.hook}** — ${p.when}`);
      lines.push(`> ${p.body}`, "");
    });
  }

  lines.push("---");
  lines.push(`*Intel Engine · Generated ${new Date().toISOString().slice(0,10)}*`);
  return lines.join("\n");
}

function ExportTab({ state }) {
  const [copied, setCopied] = useStateApp(null);
  const { isMobile } = useViewportApp();
  const copy = (text, key) => {
    navigator.clipboard.writeText(text);
    setCopied(key);
    setTimeout(() => setCopied(null), 1500);
  };
  const clientMd = buildMarkdown(state, "client");
  const internalMd = buildMarkdown(state, "internal");

  const Block = ({ title, sub, md, k }) => (
    <div style={{ marginBottom: 22 }}>
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-end", marginBottom: 10 }}>
        <div>
          <div style={{ fontFamily: T_APP.mono, fontSize: 10, color: T_APP.amberDim, letterSpacing: ".12em", textTransform: "uppercase", fontWeight: 600, marginBottom: 4 }}>{sub}</div>
          <div style={{ font: `600 18px/1.2 ${T_APP.serif}`, color: T_APP.text, letterSpacing: "-0.01em" }}>{title}</div>
        </div>
        <button onClick={() => copy(md, k)} style={{
          background: copied === k ? T_APP.green : T_APP.amber, color: "#1a1a1a", border: "none",
          padding: "8px 14px", borderRadius: 4, fontFamily: T_APP.sans, fontSize: 12, fontWeight: 600, cursor: "pointer",
        }}>{copied === k ? "✓ Copied" : "Copy markdown"}</button>
      </div>
      <pre style={{
        background: T_APP.panel, border: `1px solid ${T_APP.borderSoft}`, borderRadius: 6, padding: 16,
        fontFamily: T_APP.mono, fontSize: 11.5, color: T_APP.textDim, whiteSpace: "pre-wrap",
        maxHeight: 420, overflow: "auto", margin: 0, lineHeight: 1.6,
      }}>{md}</pre>
    </div>
  );

  return (
    <div style={{ maxWidth: 1080, margin: "0 auto", padding: isMobile ? "20px 16px 60px" : "32px 36px 80px" }}>
      <div style={{ marginBottom: 24 }}>
        <div style={{ fontFamily: T_APP.mono, fontSize: 10.5, color: T_APP.amberDim, letterSpacing: ".12em", textTransform: "uppercase", fontWeight: 600, marginBottom: 4 }}>Phase 04 — Export</div>
        <h2 style={{ font: `600 26px/1.15 ${T_APP.serif}`, margin: 0, letterSpacing: "-0.015em" }}>Export</h2>
        <p style={{ color: T_APP.textDim, maxWidth: 640, marginTop: 8, fontSize: 13, lineHeight: 1.55 }}>
          Markdown export. Stakeholder Notes, Stop Conditions, and Outreach Plays are excluded from the client surface by design — never expose these to a client.
        </p>
      </div>

      <div style={{ display: "flex", gap: 10, marginBottom: 22, flexWrap: "wrap" }}>
        <button onClick={() => {
          const i = state.intake;
          const slug = ((i.company || "search") + "-" + (i.role_title || i.role_family)).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"");
          const combined = `<!-- CLIENT-FACING -->\n\n${clientMd}\n\n\n<!-- INTERNAL -->\n\n${internalMd}`;
          const blob = new Blob([combined], { type: "text/markdown" });
          const a = document.createElement("a");
          a.href = URL.createObjectURL(blob);
          a.download = `intel-brief-${slug}.md`;
          a.click();
        }} style={{
          background: "transparent", color: T_APP.text, border: `1px solid ${T_APP.border}`,
          padding: "9px 16px", borderRadius: 4, fontFamily: T_APP.sans, fontSize: 12.5, fontWeight: 500, cursor: "pointer",
        }}>↓ Download both as .md</button>
      </div>

      <Block title="Client-facing brief" sub="Surface 1" md={clientMd} k="client" />
      <Block title="Internal brief" sub="Surface 2 — full" md={internalMd} k="internal" />
    </div>
  );
}

/* ------------- ROOT APP ------------- */
function App() {
  const [intake, setIntake] = useStateApp(window.IE_DATA.ANDY_CASE);
  const [tab, setTab] = useStateApp("brief");
  const [surface, setSurface] = useStateApp("internal");
  const [tweaks, setTweaks] = window.useTweaks(TWEAK_DEFAULTS);
  const { isMobile } = useViewportApp();
  // LLM synthesis — replaces templated thesisLine + thesis when /api/synthesize is reachable.
  // { status: "idle" | "loading" | "ok" | "error", thesisLine?: string, thesis?: string, error?: string }
  const [synth, setSynth] = useStateApp({ status: "idle" });
  const state = React.useMemo(() => buildState(intake), [intake]);

  const onGenerate = () => {
    setTab("diagnostic");
    window.scrollTo({ top: 0, behavior: "smooth" });
    // Fire LLM synthesis in the background. Brief renders templated output until this resolves.
    setSynth({ status: "loading" });
    fetch("/api/synthesize", {
      method: "POST",
      headers: { "content-type": "application/json" },
      body: JSON.stringify(intake),
    })
      .then(r => r.json().then(body => ({ ok: r.ok, status: r.status, body })))
      .then(({ ok, status, body }) => {
        if (ok && body.thesisLine && body.thesis) {
          setSynth({ status: "ok", thesisLine: body.thesisLine, thesis: body.thesis, meta: body.meta });
        } else {
          setSynth({ status: "error", error: body.error || `HTTP ${status}` });
        }
      })
      .catch(e => setSynth({ status: "error", error: String(e) }));
  };

  // Auto-resynthesize when intake changes (debounced) — but only AFTER first generate.
  useEffectApp(() => {
    if (synth.status === "idle") return; // never synthesized yet — wait for explicit Generate
    const t = setTimeout(() => {
      setSynth(s => ({ ...s, status: "loading" }));
      fetch("/api/synthesize", {
        method: "POST",
        headers: { "content-type": "application/json" },
        body: JSON.stringify(intake),
      })
        .then(r => r.json().then(body => ({ ok: r.ok, status: r.status, body })))
        .then(({ ok, status, body }) => {
          if (ok && body.thesisLine && body.thesis) {
            setSynth({ status: "ok", thesisLine: body.thesisLine, thesis: body.thesis, meta: body.meta });
          } else {
            setSynth({ status: "error", error: body.error || `HTTP ${status}` });
          }
        })
        .catch(e => setSynth({ status: "error", error: String(e) }));
    }, 1200);
    return () => clearTimeout(t);
  }, [intake]);

  return (
    <div style={{ minHeight: "100vh", background: T_APP.bg, color: T_APP.text, fontFamily: T_APP.sans }}>
      <TopBar tab={tab} setTab={setTab} density={tweaks.density} />

      {tab === "intake" && (
        <Intake intake={intake} setIntake={setIntake} onGenerate={onGenerate} />
      )}

      {tab === "diagnostic" && (
        <div style={{ maxWidth: 880, margin: "0 auto", padding: isMobile ? "20px 16px 60px" : "32px 36px 80px" }}>
          <div style={{ marginBottom: 24 }}>
            <div style={{ fontFamily: T_APP.mono, fontSize: 10.5, color: T_APP.amberDim, letterSpacing: ".12em", textTransform: "uppercase", fontWeight: 600, marginBottom: 4 }}>Phase 02 — Diagnostic</div>
            <h2 style={{ font: `600 26px/1.15 ${T_APP.serif}`, margin: 0, letterSpacing: "-0.015em" }}>Search Diagnostic</h2>
            <p style={{ color: T_APP.textDim, maxWidth: 580, marginTop: 8, fontSize: 13, lineHeight: 1.55 }}>
              Five gates. Failed gates surface first — that's the value. Two or more failures means the search is at material risk, and the conversation belongs with the client before sourcing.
            </p>
          </div>
          <Diagnostic diag={state.diag} />
        </div>
      )}

      {tab === "brief" && (
        <Brief
          state={state}
          surface={surface}
          setSurface={setSurface}
          density={tweaks.density}
          internalVisible={tweaks.showInternalSections}
          synth={synth}
        />
      )}

      {tab === "export" && <ExportTab state={state} />}

      {/* Tweaks panel */}
      <window.TweaksPanel title="Tweaks">
        <window.TweakSection label="Density">
          <window.TweakRadio
            value={tweaks.density}
            onChange={(v) => setTweaks({ density: v })}
            options={[{ value: "comfortable", label: "Comfortable" }, { value: "compact", label: "Compact" }]}
          />
        </window.TweakSection>
        <window.TweakSection label="Brief layout">
          <window.TweakRadio
            value={tweaks.briefLayout}
            onChange={(v) => setTweaks({ briefLayout: v })}
            options={[{ value: "left-nav", label: "Left-nav" }, { value: "long-scroll", label: "Long-scroll" }]}
          />
        </window.TweakSection>
        <window.TweakSection label="Internal-only sections">
          <window.TweakToggle
            value={tweaks.showInternalSections}
            onChange={(v) => setTweaks({ showInternalSections: v })}
            label={tweaks.showInternalSections ? "Visible (Stakeholder Notes, Stop Conditions, Outreach Plays)" : "Hidden"}
          />
        </window.TweakSection>
      </window.TweaksPanel>
    </div>
  );
}

ReactDOM.createRoot(document.getElementById("root")).render(<App />);
