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

/* ---- typing hook: types `full` once `start` is true ---- */
function useTyping(full, start, speed = 34) {
  const [n, setN] = useState(0);
  useEffect(() => {
    if (!start) return;
    const reduce = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
    if (reduce) { setN(full.length); return; }
    let i = 0;
    const id = setInterval(() => {
      i++; setN(i);
      if (i >= full.length) clearInterval(id);
    }, speed);
    return () => clearInterval(id);
  }, [full, start, speed]);
  return full.slice(0, n);
}

/* ---- intersection visibility ---- */
function useInView(threshold = 0.3) {
  const ref = useRef(null);
  const [seen, setSeen] = useState(false);
  useEffect(() => {
    const el = ref.current; if (!el) return;
    const io = new IntersectionObserver((es) => {
      es.forEach((e) => { if (e.isIntersecting) { setSeen(true); io.disconnect(); } });
    }, { threshold });
    io.observe(el);
    return () => io.disconnect();
  }, [threshold]);
  return [ref, seen];
}

/* ============================================================
   SchematicPanel — the recurring "describe → generated" device.
   Renders a window with a typing prompt + a 2-stage Miller OTA
   schematic that strokes itself in on view.
   ============================================================ */
function SchematicPanel({ prompt = "Design a 2-stage Miller OTA, GBW \u2265 30 MHz, PM \u2265 60\u00b0", status = "draft_schematic", compact = false }) {
  const [ref, seen] = useInView(0.25);
  const typed = useTyping(prompt, seen, 26);
  const done = typed.length >= prompt.length;
  const [secs] = useState(() => (2 + Math.random() * 1.4).toFixed(2));

  // device boxes: [x, y, label]
  const dev = [
    [196, 92, "M3"], [320, 92, "M4"],
    [196, 196, "M1"], [320, 196, "M2"],
    [258, 286, "M5"],
    [452, 110, "M6"], [452, 270, "M7"],
  ];
  const W = 30, H = 22;
  const cx = (x) => x + W / 2;

  // orthogonal wires (drawn in order, staggered)
  const wires = [
    // VDD rail
    "M60,52 H520",
    // M3/M4 sources up to VDD
    `M${cx(196)},92 V52`, `M${cx(320)},92 V52`,
    // mirror gates tie + diode connect
    "M211,103 H335",
    // M3 drain -> M1 drain
    `M${cx(196)},114 V196`,
    // M4 drain -> M2 drain (stage-1 out node)
    `M${cx(320)},114 V196`,
    // diff pair sources -> tail
    `M${cx(196)},218 V262 H${cx(258)} V286`,
    `M${cx(320)},218 V262 H${cx(258)}`,
    // tail to GND
    `M${cx(258)},308 V392`,
    // inputs
    `M96,207 H196`, `M450,207 H350`,
    // stage-1 out node -> M6 gate
    `M${cx(320)},152 H${cx(452)} V110`,
    // M6 source to VDD
    `M${cx(452)},110 V52`,
    // M6 drain -> out -> M7 drain
    `M${cx(452)},132 V270`,
    // out tap
    `M${cx(452)},201 H520`,
    // M7 source to GND
    `M${cx(452)},292 V392`,
    // M7 gate bias
    `M452,281 H398`,
    // GND rail
    "M60,392 H520",
    // comp cap Cc between out and stage-1-out node
    `M${cx(320)},168 H400 V201 H${cx(452)}`,
  ];

  const reduce = typeof window !== "undefined" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;

  return (
    <div className="window schempanel" ref={ref}>
      <div className="window__bar">
        <span className="schempanel__caret">{"\u203a"}</span>
        <span className="schempanel__prompt">
          {typed}{!done && <span className="caret" />}
        </span>
        <span className="spacer" />
        <span className="status-chip">
          {done ? <Check /> : <Spin />}
          {status} {done ? secs + "s" : ""}
        </span>
      </div>
      <div className="schempanel__body dotgrid">
        <svg viewBox="0 0 560 430" className={"schem " + (seen ? "is-in" : "")} preserveAspectRatio="xMidYMid meet">
          {/* rails labels */}
          <text x="40" y="56" className="schem__rail">VDD</text>
          <text x="40" y="396" className="schem__rail">GND</text>
          {/* wires */}
          {wires.map((d, i) => (
            <path key={i} d={d} className="wire" pathLength="1"
              style={{ animationDelay: reduce ? "0s" : (0.25 + i * 0.045) + "s" }} />
          ))}
          {/* nodes */}
          <Node x={96} y={207} label="in+" seen={seen} d={0.1} />
          <Node x={450} y={207} label="in\u2212" seen={seen} align="end" d={0.16} />
          <Node x={398} y={281} label="Vbn" seen={seen} align="end" d={0.5} />
          <Node x={258} y={286 + 11} label="" seen={seen} d={0.4} />
          {/* Cc label */}
          <text x="372" y="184" className="schem__lbl">Cc</text>
          <text x="372" y="196" className="schem__lbl schem__lbl--dim">2pF</text>
          {/* out node */}
          <g className={"schem__out " + (done ? "live" : "")}>
            <circle cx="520" cy="201" r="3.4" />
            <text x="528" y="205" className="schem__lbl schem__lbl--out">out</text>
          </g>
          {/* devices */}
          {dev.map(([x, y, l], i) => (
            <g key={l} className="dev" style={{ animationDelay: reduce ? "0s" : (0.15 + i * 0.07) + "s" }}>
              <rect x={x} y={y} width={W} height={H} rx="3.5" />
              <text x={x + W + 5} y={y + 15} className="schem__lbl">{l}</text>
            </g>
          ))}
        </svg>
      </div>
    </div>
  );
}

function Node({ x, y, label, align = "start", seen, d = 0 }) {
  return (
    <g className="schem__node" style={{ animationDelay: (0.3 + d) + "s" }}>
      <circle cx={x} cy={y} r="3" />
      {label && (
        <text x={align === "end" ? x - 8 : x + 8} y={y + 4}
          className="schem__lbl" textAnchor={align}>{label}</text>
      )}
    </g>
  );
}

function Check() {
  return <svg width="11" height="11" viewBox="0 0 12 12" fill="none"><path d="M2.5 6.2 5 8.6 9.6 3.4" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"/></svg>;
}
function Spin() {
  return <svg width="11" height="11" viewBox="0 0 12 12" className="spin" fill="none"><circle cx="6" cy="6" r="4.4" stroke="currentColor" strokeOpacity="0.3" strokeWidth="1.5"/><path d="M6 1.6A4.4 4.4 0 0 1 10.4 6" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round"/></svg>;
}

Object.assign(window, { SchematicPanel, useTyping, useInView, Check, Spin });
