/* crabcc landing — terminal + install components
   Exports to window for cross-file sharing. */
const { useState, useEffect, useRef } = React;

/* ---- syntax-token helper: render a parsed JSON-ish line ---- */
function Tok({ t, v }) {
  return <span className={"tk-" + t}>{v}</span>;
}

/* A scripted terminal session: types each command char-by-char,
   then reveals its output rows, then moves to the next command.
   Loops. Honors reduced motion (renders final frame statically). */
function TypedTerminal() {
  // Each "scene" = a command + its output rows (arrays of tokens)
  const scenes = [
    {
      cmd: [
        { t: "cmd", v: "crabcc " },
        { t: "cmd", v: "sym " },
        { t: "cmd", v: "Assessment" },
      ],
      out: [
        [{ t: "punc", v: "[" }],
        [{ t: "punc", v: "  { " }, { t: "key", v: '"name"' }, { t: "punc", v: ": " }, { t: "str", v: '"Assessment"' }, { t: "punc", v: ", " }, { t: "key", v: '"kind"' }, { t: "punc", v: ": " }, { t: "str", v: '"class"' }, { t: "punc", v: ", " }, { t: "key", v: '"file"' }, { t: "punc", v: ": " }, { t: "str", v: '"core/model.rs"' }, { t: "punc", v: ", " }, { t: "key", v: '"line"' }, { t: "punc", v: ": " }, { t: "num", v: "42" }, { t: "punc", v: " }," }],
        [{ t: "punc", v: "  { " }, { t: "key", v: '"name"' }, { t: "punc", v: ": " }, { t: "str", v: '"Assessment"' }, { t: "punc", v: ", " }, { t: "key", v: '"kind"' }, { t: "punc", v: ": " }, { t: "str", v: '"fn"' }, { t: "punc", v: ", " }, { t: "key", v: '"file"' }, { t: "punc", v: ": " }, { t: "str", v: '"api/handlers.rs"' }, { t: "punc", v: ", " }, { t: "key", v: '"line"' }, { t: "punc", v: ": " }, { t: "num", v: "118" }, { t: "punc", v: " }" }],
        [{ t: "punc", v: "]" }],
        [{ t: "dim", v: "3 symbols · 1.9ms · 253 bytes" }],
      ],
    },
    {
      cmd: [
        { t: "cmd", v: "crabcc " },
        { t: "cmd", v: "callers " },
        { t: "cmd", v: "handleAuth " },
        { t: "flag", v: "--count" },
      ],
      out: [
        [{ t: "punc", v: "{ " }, { t: "key", v: '"count"' }, { t: "punc", v: ": " }, { t: "num", v: "7" }, { t: "punc", v: " }" }],
        [{ t: "dim", v: "↳ 62,541 bytes → 12 bytes  (−99.98%)" }],
      ],
    },
    {
      cmd: [
        { t: "cmd", v: "crabcc " },
        { t: "cmd", v: "refs " },
        { t: "cmd", v: "Store " },
        { t: "flag", v: "--files-only" },
      ],
      out: [
        [{ t: "str", v: "core/store.rs" }],
        [{ t: "str", v: "core/index.rs" }],
        [{ t: "str", v: "api/server.rs" }],
        [{ t: "dim", v: "3 files · 0.8ms" }],
      ],
    },
  ];

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

  const [sceneI, setSceneI] = useState(0);
  const [typed, setTyped] = useState(reduce ? 999 : 0); // chars of command shown
  const [showOut, setShowOut] = useState(reduce);
  const [history, setHistory] = useState([]); // completed scenes kept on screen (max 1 prior)

  const scene = scenes[sceneI];
  const cmdText = scene.cmd.map((c) => c.v).join("");

  useEffect(() => {
    if (reduce) return;
    let timer;
    if (typed < cmdText.length) {
      timer = setTimeout(() => setTyped((n) => n + 1), 38 + Math.random() * 36);
    } else if (!showOut) {
      timer = setTimeout(() => setShowOut(true), 360);
    } else {
      // hold, then advance
      timer = setTimeout(() => {
        setHistory((h) => [{ cmd: scene.cmd, out: scene.out }].slice(0, 1));
        setSceneI((i) => (i + 1) % scenes.length);
        setTyped(0);
        setShowOut(false);
      }, 2600);
    }
    return () => clearTimeout(timer);
  }, [typed, showOut, sceneI]);

  // build the partially-typed command tokens
  const renderTypedCmd = () => {
    let remaining = typed;
    const parts = [];
    for (const seg of scene.cmd) {
      if (remaining <= 0) break;
      const slice = seg.v.slice(0, remaining);
      parts.push(<Tok key={parts.length} t={seg.t === "flag" ? "flag" : "cmd"} v={slice} />);
      remaining -= seg.v.length;
    }
    return parts;
  };

  const Line = ({ row }) => (
    <span className="term__line">
      {row.map((tk, i) => <Tok key={i} t={tk.t} v={tk.v} />)}
    </span>
  );

  const typing = typed < cmdText.length;

  return (
    <div className="term" role="img" aria-label="crabcc terminal: querying symbols and getting compact JSON back">
      <div className="term__bar">
        <span className="term__dot term__dot--r"></span>
        <span className="term__dot term__dot--y"></span>
        <span className="term__dot term__dot--g"></span>
        <span className="term__title">crabcc — <span className="pwd">~/monorepo</span></span>
      </div>
      <div className="term__body">
        {history.map((h, hi) => (
          <React.Fragment key={"h" + hi + sceneI}>
            <span className="term__line"><span className="tk-prompt">$ </span>{h.cmd.map((c, i) => <Tok key={i} t={c.t === "flag" ? "flag" : "cmd"} v={c.v} />)}</span>
            {h.out.map((row, ri) => <Line key={ri} row={row} />)}
            <span className="term__line">{"\u00A0"}</span>
          </React.Fragment>
        ))}
        <span className="term__line">
          <span className="tk-prompt">$ </span>
          {reduce ? scene.cmd.map((c, i) => <Tok key={i} t={c.t === "flag" ? "flag" : "cmd"} v={c.v} />) : renderTypedCmd()}
          {typing && <span className="cursor"></span>}
        </span>
        {showOut && scene.out.map((row, ri) => <Line key={ri} row={row} />)}
      </div>
    </div>
  );
}

/* Install one-liner with copy-to-clipboard */
function InstallLine({ cmd = "cargo install crabcc", className = "" }) {
  const [copied, setCopied] = useState(false);
  const doCopy = () => {
    const text = "$ " + cmd;
    try {
      navigator.clipboard.writeText(cmd);
    } catch (e) { /* ignore */ }
    setCopied(true);
    setTimeout(() => setCopied(false), 1600);
  };
  return (
    <div className={"install " + className}>
      <span className="install__prompt">$</span>
      <span className="install__cmd">{cmd}</span>
      <button className={"install__copy" + (copied ? " is-copied" : "")} onClick={doCopy} aria-label="Copy install command">
        {copied ? "✓ copied" : "copy"}
      </button>
    </div>
  );
}

Object.assign(window, { TypedTerminal, InstallLine, Tok });
