/* global React */
const { useEffect, useRef, useState } = React;

/* Static-first SVG diagrams, gated by IntersectionObserver for one-pass reveal.
   Style: 1.5px navy strokes, indigo accent for active node + pulses.
*/

const diagramStyles = {
  wrap: {
    position: 'relative',
    background: 'var(--bg-2)',
    border: 'var(--border-hair)',
    borderRadius: 'var(--r-3)',
    padding: 'var(--s-3)',
    aspectRatio: '15 / 8',
    minHeight: 200,
  },
  replayBtn: {
    position: 'absolute', top: 12, right: 12, zIndex: 2,
    display: 'inline-flex', alignItems: 'center', gap: 6,
    padding: '6px 10px', borderRadius: 'var(--r-1)',
    border: '1px solid var(--line-1)', background: 'var(--bg-1)',
    fontSize: 11, fontWeight: 500, letterSpacing: '0.08em', textTransform: 'uppercase',
    color: 'var(--fg-2)', cursor: 'pointer',
  },
  svg: { width: '100%', height: '100%', display: 'block' },
};

function useReveal(ref) {
  const [shown, setShown] = useState(false);
  useEffect(() => {
    const el = ref.current; if (!el) return;
    const io = new IntersectionObserver((entries) => {
      entries.forEach(e => { if (e.isIntersecting) { setShown(true); io.disconnect(); }});
    }, { threshold: 0.3 });
    io.observe(el);
    return () => io.disconnect();
  }, [ref]);
  return [shown, () => setShown(false)];
}

/* ---------- shared helpers --------------------------------------------- */
const Node = ({ x, y, w = 88, h = 38, label, sub, active, kind = 'rect', dashed }) => {
  const stroke = active ? 'var(--latus-indigo)' : 'var(--latus-dark-blue)';
  const fill = active ? 'var(--latus-light-blue)' : 'var(--bg-1)';
  const strokeProps = dashed ? { strokeDasharray: '3 3' } : {};
  return (
    <g>
      {kind === 'rect' && <rect x={x - w/2} y={y - h/2} width={w} height={h} rx="2" fill={fill} stroke={stroke} strokeWidth="1.5" {...strokeProps}/>}
      {kind === 'diamond' && (
        <polygon points={`${x},${y-h/2} ${x+w/2},${y} ${x},${y+h/2} ${x-w/2},${y}`} fill={fill} stroke={stroke} strokeWidth="1.5"/>
      )}
      {kind === 'cyl' && (
        <g fill={fill} stroke={stroke} strokeWidth="1.5">
          <ellipse cx={x} cy={y - h/2} rx={w/2} ry={6}/>
          <path d={`M${x-w/2} ${y-h/2} L${x-w/2} ${y+h/2} A${w/2} 6 0 0 0 ${x+w/2} ${y+h/2} L${x+w/2} ${y-h/2}`}/>
          <ellipse cx={x} cy={y - h/2} rx={w/2} ry={6} fill="none"/>
        </g>
      )}
      {kind === 'stack' && (
        // depict "many of them" — three slightly offset rects
        <g fill={fill} stroke={stroke} strokeWidth="1.5">
          <rect x={x - w/2 + 6} y={y - h/2 + 6} width={w} height={h} rx="2"/>
          <rect x={x - w/2 + 3} y={y - h/2 + 3} width={w} height={h} rx="2"/>
          <rect x={x - w/2}     y={y - h/2}     width={w} height={h} rx="2"/>
        </g>
      )}
      <text x={x} y={y - (sub ? 3 : 4)} textAnchor="middle" dominantBaseline="middle"
        fontFamily="var(--font-sans)" fontSize="12" fontWeight="500" fill="var(--latus-dark-blue)">{label}</text>
      {sub && <text x={x} y={y + 11} textAnchor="middle" dominantBaseline="middle"
        fontFamily="var(--font-sans)" fontSize="10.5" fontWeight="400" fill="var(--fg-2)">{sub}</text>}
    </g>
  );
};

const Edge = ({ d, animate, dur = 1200, delay = 0, active, dashed, label, labelX, labelY }) => (
  <g>
    <path d={d} fill="none"
      stroke={active ? 'var(--latus-indigo)' : 'var(--latus-dark-blue)'}
      strokeWidth="1.25"
      opacity={active ? 0.9 : 0.45}
      strokeDasharray={dashed ? '4 4' : undefined}
      markerEnd="url(#arrow)"/>
    {animate && (
      <circle r="3.5" fill="var(--latus-indigo)">
        <animateMotion dur={`${dur}ms`} begin={`${delay}ms`} fill="freeze" path={d}/>
        <animate attributeName="opacity" from="0" to="1" dur="120ms" begin={`${delay}ms`} fill="freeze"/>
        <animate attributeName="opacity" from="1" to="0" dur="240ms" begin={`${delay + dur - 240}ms`} fill="freeze"/>
      </circle>
    )}
    {label && <text x={labelX} y={labelY} textAnchor="middle"
      fontFamily="var(--font-sans)" fontSize="10.5" fontWeight="500" fill="var(--fg-2)" letterSpacing="0.04em">{label}</text>}
  </g>
);

const Annotation = () => null;

const ContainerLabel = ({ x, y, children }) => (
  <text x={x} y={y} fontFamily="var(--font-sans)" fontSize="11" fontWeight="500"
    letterSpacing="0.12em" fill="var(--fg-3)">{typeof children === 'string' ? children.toUpperCase() : children}</text>
);

const Defs = () => (
  <defs>
    <marker id="arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
      <path d="M 0 0 L 10 5 L 0 10 z" fill="var(--latus-dark-blue)"/>
    </marker>
    <pattern id="dgrid" width="20" height="20" patternUnits="userSpaceOnUse">
      <circle cx="10" cy="10" r="0.6" fill="rgba(3,31,88,0.18)"/>
    </pattern>
  </defs>
);

const ReplayButton = ({ onClick }) => (
  <button style={diagramStyles.replayBtn} onClick={onClick} className="no-print">
    <svg width="11" height="11" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.5"><path d="M14 8a6 6 0 1 1-2-4.5"/><path d="M14 3v3h-3"/></svg>
    Replay
  </button>
);

/* ---------- 1 · Medical AI Search -------------------------------------- */
function DiagramMedicalSearch({ replayKey, replay }) {
  const ref = useRef(null);
  const [shown, reset] = useReveal(ref);
  const playing = shown || replayKey > 0;
  return (
    <div ref={ref} style={diagramStyles.wrap}>
      <ReplayButton onClick={() => { reset(); setTimeout(replay, 30); }}/>
      <svg viewBox="0 0 600 320" style={diagramStyles.svg} key={`med-${replayKey}`}>
        <Defs/>
        <rect width="600" height="320" fill="url(#dgrid)"/>

        {/* main flow on y=200, edge centers */}
        <Edge d="M 108 200 H 128" animate={playing} delay={0}/>
        <Edge d="M 224 200 H 244" animate={playing} delay={500}/>
        <Edge d="M 348 200 H 368" animate={playing} delay={1000}/>
        <Edge d="M 472 200 H 492" animate={playing} delay={1500}/>

        {/* ingestion (dashed, top-down into Index top edge) */}
        <Edge d="M 420 108 V 172" dashed label="ingested" labelX={460} labelY={140}/>

        <Node x={60}  y={200} w={96}  h={56} label="Clinicians" sub="website"/>
        <Node x={176} y={200} w={96}  h={56} label="Search API" sub="FastAPI"/>
        <Node x={296} y={200} kind="diamond" w={104} h={88} label="Sanitise" sub="strip PII" active={playing}/>
        <Node x={420} y={200} kind="cyl" w={104} h={56} label="Index" sub="Azure AI Search"/>
        <Node x={540} y={200} w={96}  h={56} label="Results"/>

        <Node x={420} y={80}  kind="cyl" w={160} h={56} label="Clinical guidelines" sub="11,000+ documents"/>

        <Annotation x={296} y={266} anchor="middle">PII stripped inside the API, before the index</Annotation>
        <Annotation x={540} y={150} anchor="middle">Off-the-shelf vector index</Annotation>
      </svg>
    </div>
  );
}

/* ---------- 2 · Self-service data warehouse ---------------------------- */
function DiagramDataWarehouse({ replayKey, replay }) {
  const ref = useRef(null);
  const [shown, reset] = useReveal(ref);
  const playing = shown || replayKey > 0;
  return (
    <div ref={ref} style={diagramStyles.wrap}>
      <ReplayButton onClick={() => { reset(); setTimeout(replay, 30); }}/>
      <svg viewBox="0 0 600 320" style={diagramStyles.svg} key={`dw-${replayKey}`}>
        <Defs/>
        <rect width="600" height="320" fill="url(#dgrid)"/>

        {/* Sources → Combine diamond (diagonals into the diamond's left tip) */}
        <Edge d="M 108 86 L 132 200"  animate={playing} delay={0}/>
        <Edge d="M 108 280 L 132 200" animate={playing} delay={350}/>
        {/* Combine → Warehouse → Use case (main spine at y=200, edge centers) */}
        <Edge d="M 252 200 H 268" animate={playing} delay={700}/>
        <Edge d="M 356 200 H 384" animate={playing} delay={1050}/>
        {/* Use case top-center → Insight left-center (up then right) */}
        <Edge d="M 432 172 V 86 H 500" animate={playing} delay={1400}/>
        {/* Use case bottom-center → Analyst left-center (down then right) */}
        <Edge d="M 432 228 V 280 H 500" animate={playing} delay={1750}/>
        {/* Triggers (dashed feedback) — routes over the top, into Use case left-center */}
        <Edge d="M 588 280 H 600 V 40 H 380 V 200 H 384" dashed label="triggers" labelX={490} labelY={30}/>

        <Node x={64}  y={86}  kind="cyl" w={88}  h={56} label="Scraped"   sub="unstructured"/>
        <Node x={64}  y={280} kind="cyl" w={88}  h={56} label="APIs"      sub="structured"/>
        <Node x={192} y={200} kind="diamond" w={120} h={88} label="Combine" sub="+ quality checks" active={playing}/>
        <Node x={312} y={200} kind="cyl" w={88}  h={56} label="Warehouse" sub="BigQuery"/>
        <Node x={432} y={200} w={96}  h={56} label="Use case"  sub="pre-built"/>
        <Node x={544} y={86}  w={88}  h={56} label="Insight"   sub="or report"/>
        <Node x={544} y={280} w={88}  h={56} label="Analyst"/>

        <Annotation x={192} y={264} anchor="middle">Quality gate before the warehouse</Annotation>
      </svg>
    </div>
  );
}

/* ---------- 3 · Financial doc pipeline --------------------------------- */
function DiagramFinancialDocs({ replayKey, replay }) {
  const ref = useRef(null);
  const [shown, reset] = useReveal(ref);
  const playing = shown || replayKey > 0;
  return (
    <div ref={ref} style={diagramStyles.wrap}>
      <ReplayButton onClick={() => { reset(); setTimeout(replay, 30); }}/>
      <svg viewBox="0 0 600 320" style={diagramStyles.svg} key={`fin-${replayKey}`}>
        <Defs/>
        <rect width="600" height="320" fill="url(#dgrid)"/>

        {/* Main spine at y=180, edge-centered, uniform w=88 spacing */}
        <Edge d="M 100 180 H 124" animate={playing} delay={0}/>
        <Edge d="M 212 180 H 236" animate={playing} delay={400}/>
        <Edge d="M 324 180 H 348" animate={playing} delay={800}/>
        <Edge d="M 436 180 H 460" animate={playing} delay={1200}/>

        {/* Validate top tip → Output bottom-center (passes) */}
        <Edge d="M 520 136 V 108" animate={playing} delay={1700} label="passes" labelX={532} labelY={124}/>

        {/* Validate bottom tip → Human top-center (low confidence) */}
        <Edge d="M 520 224 V 262" animate={playing} delay={2200} label="low confidence" labelX={532} labelY={244}/>

        {/* Validate left tip → up → left → Extract top-center (dashed retry) */}
        <Edge d="M 460 180 V 60 H 392 V 152" animate={playing} delay={2700} dashed label="ambiguous — retry" labelX={426} labelY={50}/>

        <Node x={56}  y={180} w={88}  h={56} label="Scanned"  sub="document"/>
        <Node x={168} y={180} w={88}  h={56} label="OCR"      sub="Azure"/>
        <Node x={280} y={180} w={88}  h={56} label="Classify" sub="doc type"/>
        <Node x={392} y={180} w={88}  h={56} label="Extract"  sub="fields"/>
        <Node x={520} y={180} kind="diamond" w={120} h={88} label="Validate" sub="cross-field" active={playing}/>
        <Node x={520} y={80}  w={96}  h={56} label="Output"   sub="structured"/>
        <Node x={520} y={290} w={96}  h={56} label="Human"    sub="review"/>

        <Annotation x={140} y={30} anchor="middle">Hard gate — totals must reconcile</Annotation>
      </svg>
    </div>
  );
}

/* ---------- 4 · Legal case-analysis ------------------------------------ */
function DiagramLegalCase({ replayKey, replay }) {
  const ref = useRef(null);
  const [shown, reset] = useReveal(ref);
  const playing = shown || replayKey > 0;
  return (
    <div ref={ref} style={diagramStyles.wrap}>
      <ReplayButton onClick={() => { reset(); setTimeout(replay, 30); }}/>
      <svg viewBox="0 0 600 320" style={diagramStyles.svg} key={`leg-${replayKey}`}>
        <Defs/>
        <rect width="600" height="320" fill="url(#dgrid)"/>

        {/* Top row at y=110, edge-centered, uniform w=96 spacing */}
        <Edge d="M 112 110 H 134" animate={playing} delay={0}/>
        <Edge d="M 230 110 H 252" animate={playing} delay={400}/>
        <Edge d="M 348 110 H 370" animate={playing} delay={800}/>
        <Edge d="M 466 110 H 488" animate={playing} delay={1200}/>
        {/* Rules → Caseworker UI: vertical down into top edge */}
        <Edge d="M 536 138 V 232" animate={playing} delay={1600}/>
        {/* OCR → Chat-to-docs (dashed, also feeds): vertical down into top edge */}
        <Edge d="M 182 138 V 232" animate={playing} delay={2000} dashed label="also feeds" labelX={138} labelY={188}/>
        {/* Chat-to-docs → Caseworker UI: horizontal between edge centers */}
        <Edge d="M 192 260 H 416" animate={playing} delay={2400}/>

        <Node x={64}  y={110} w={96}  h={56} label="Contracts" sub="PDFs"/>
        <Node x={182} y={110} w={96}  h={56} label="OCR"       sub="GCP"/>
        <Node x={300} y={110} w={96}  h={56} label="Retrieve"  sub="clauses"/>
        <Node x={418} y={110} w={96}  h={56} label="Reason"    sub="LLM agent" active={playing}/>
        <Node x={536} y={110} w={96}  h={56} label="Rules"     sub="business"/>
        <Node x={104} y={260} w={176} h={56} label="Chat-to-docs" sub="direct verification"/>
        <Node x={504} y={260} w={176} h={56} label="Caseworker UI" sub="answer + citations"/>

        <Annotation x={360} y={56}  anchor="middle">Retrieve & reason are separate</Annotation>
        <Annotation x={556} y={188} anchor="middle">96% → 100% with rules</Annotation>
      </svg>
    </div>
  );
}

/* ---------- 5 · Classical ML at scale ---------------------------------- */
function DiagramClassicalML({ replayKey, replay }) {
  const ref = useRef(null);
  const [shown, reset] = useReveal(ref);
  const playing = shown || replayKey > 0;
  return (
    <div ref={ref} style={diagramStyles.wrap}>
      <ReplayButton onClick={() => { reset(); setTimeout(replay, 30); }}/>
      <svg viewBox="0 0 600 320" style={diagramStyles.svg} key={`ml-${replayKey}`}>
        <Defs/>
        <rect width="600" height="320" fill="url(#dgrid)"/>

        {/* Top row at y=110 */}
        <Edge d="M 108 110 H 128" animate={playing} delay={0}/>
        <Edge d="M 244 110 H 264" animate={playing} delay={400}/>
        <Edge d="M 380 110 H 400" animate={playing} delay={800}/>

        {/* Snake from Prophet bottom-center down then back to Anomaly top-center */}
        <Edge d="M 458 138 V 220 H 148 V 232" animate={playing} delay={1200}/>

        {/* Bottom row at y=260: Anomaly right → Power BI left; Power BI right → Ops left */}
        <Edge d="M 196 260 H 264" animate={playing} delay={1600}/>
        <Edge d="M 380 260 H 408" animate={playing} delay={2000}/>

        <Node x={60}  y={110} w={96}  h={56} label="Anna"      sub="8,000 nodes"/>
        <Node x={186} y={110} kind="cyl" w={116} h={56} label="Per-node"  sub="time-series"/>
        <Node x={322} y={110} w={116} h={56} label="PySpark"   sub="on Databricks" active={playing}/>
        <Node x={458} y={110} kind="stack" w={116} h={56} label="Prophet × 8K" sub="one per node"/>

        <Node x={148} y={260} w={96}  h={56} label="Anomaly"   sub="scores"/>
        <Node x={322} y={260} w={116} h={56} label="Power BI"  sub="dashboard"/>
        <Node x={464} y={260} w={112} h={56} label="Ops"       sub="triage"/>

        <Annotation x={322} y={186} anchor="middle">8,000 runs in parallel</Annotation>
        <Annotation x={458} y={186} anchor="middle">Off-the-shelf Prophet</Annotation>
      </svg>
    </div>
  );
}

Object.assign(window, {
  DiagramMedicalSearch, DiagramDataWarehouse,
  DiagramFinancialDocs, DiagramLegalCase, DiagramClassicalML,
});
