/* crabcc landing — AI-native tools:
   (1) Copy-as-context (page Markdown + per-section + Open in Claude/ChatGPT)
   (2) Token-cost calculator
   (3) Trust signals (signed releases + checksums + verified badge)
   Exports to window. */
const { useState: useStateA2 } = React;

/* ---------- shared page markdown (also written to crabcc.md) ---------- */
const PAGE_MD = `# crabcc — symbol index for AI coding agents

crabcc is a small Rust CLI + MCP server that indexes your repo's symbols
(functions, classes, methods) into a SQLite store and answers four queries an
agent actually wants — **sym**, **refs**, **callers**, **outline** — as typed
JSON, for a fraction of the tokens a grep dump costs.

- **Up to 4412× faster** than \`grep -rn\` (13k-file Rust monorepo, warm index).
- **85% fewer bytes** to the model on average (−99.6% best case).
- **~250ms** no-op re-index. Built on Rust + SQLite + Tantivy.

## The four primitives
| command | answers |
|---|---|
| \`crabcc sym Foo\` | where is this defined? (kind, file, line) |
| \`crabcc refs Foo\` | every reference, deduped by file |
| \`crabcc callers fn\` | who calls this function |
| \`crabcc outline file.rs\` | the symbols of a file, in order |

Shape the output with \`--count\`, \`--files-only\`, \`--limit\` to collapse a
16k-token result to ~3 tokens.

## Install
\`\`\`
cargo install crabcc
\`\`\`

## MCP
Same four code paths ship over JSON-RPC 2.0 as an MCP server (stdio, stateless,
read-only). Point Claude Code / Cursor at it. Schema: mcp-schema.json.
`;

const SECTION_MD = {
  primitives: "## crabcc — the four primitives\n- `crabcc sym Foo` — where is this defined? (kind, file, line)\n- `crabcc refs Foo` — every reference, deduped by file\n- `crabcc callers fn` — who calls this function\n- `crabcc outline file.rs` — the symbols of a file, in order\nShape with `--count` / `--files-only` / `--limit`.",
  speed: "## crabcc — benchmarks\nUp to 4412× faster than `grep -rn` on a 13k-file Rust monorepo (warm index). grep re-walks the tree each call; crabcc answers from a SQLite symbol store.",
  savings: "## crabcc — token economy\n85% fewer bytes to the model on average. Example: `grep -rn handleAuth` = 62,541 bytes vs `crabcc callers handleAuth --count` = 253 bytes (−99.6%).",
  agents: "## crabcc — MCP server\nThe four primitives ship over JSON-RPC 2.0 as an MCP server (stdio, stateless, read-only). Point any MCP client at it; the model maps a want → a command. Schema: mcp-schema.json.",
};

const LLM_PROMPT =
  "I'm evaluating crabcc — a symbol index for AI coding agents (a Rust CLI + MCP server that indexes a repo's symbols into SQLite and answers sym/refs/callers/outline as typed JSON, up to 4412x faster than grep and ~85% fewer tokens). Help me: (1) install it with `cargo install crabcc`, (2) index my repo, (3) wire it into my agent via its MCP server (JSON-RPC 2.0, stdio).";

function copyText(text, done) {
  try { navigator.clipboard.writeText(text); } catch (e) {}
  if (done) done();
}

/* page-level copy + open-in-LLM cluster */
function AIBar() {
  const [copied, setCopied] = useStateA2(false);
  const q = encodeURIComponent(LLM_PROMPT);
  return (
    <div className="aibar">
      <button className={"aibar__btn" + (copied ? " is-copied" : "")} onClick={() => copyText(PAGE_MD, () => { setCopied(true); setTimeout(() => setCopied(false), 1600); })}>
        <span className="aibar__ico">{copied ? "✓" : "⧉"}</span>{copied ? "copied as markdown" : "copy page as markdown"}
      </button>
      <a className="aibar__btn aibar__btn--ghost" href={"https://claude.ai/new?q=" + q} target="_blank" rel="noopener">open in claude →</a>
      <a className="aibar__btn aibar__btn--ghost" href={"https://chatgpt.com/?q=" + q} target="_blank" rel="noopener">open in chatgpt →</a>
      <a className="aibar__btn aibar__btn--ghost" href="llms.txt" target="_blank" rel="noopener">llms.txt</a>
    </div>
  );
}

/* small per-section copy button (used in Head) */
function SectionCopy({ mdKey }) {
  const [copied, setCopied] = useStateA2(false);
  const md = SECTION_MD[mdKey];
  if (!md) return null;
  return (
    <button className={"sec-copy" + (copied ? " is-copied" : "")} title="Copy this section as Markdown for your agent"
      onClick={() => copyText(md, () => { setCopied(true); setTimeout(() => setCopied(false), 1500); })}>
      {copied ? "✓ copied" : "⧉ copy"}
    </button>
  );
}

/* ---------- token-cost calculator ---------- */
function TokenCalculator() {
  const { Select, Badge } = window.CrabccDesignSystem_325a37;
  const QUERIES = {
    "callers of a hot function": { grepPerKFile: 1180, crabcc: 253 },
    "find a class definition":   { grepPerKFile: 420,  crabcc: 96 },
    "all references, deduped":   { grepPerKFile: 760,  crabcc: 188 },
    "outline a file":            { grepPerKFile: 90,   crabcc: 142 },
  };
  const MODELS = {
    "claude sonnet — $3.00/Mtok":   3.0,
    "gpt-4o — $2.50/Mtok":          2.5,
    "gemini 1.5 pro — $1.25/Mtok":  1.25,
    "gpt-4o-mini — $0.15/Mtok":     0.15,
  };
  const [files, setFiles] = useStateA2(13000);
  const [query, setQuery] = useStateA2(Object.keys(QUERIES)[0]);
  const [model, setModel] = useStateA2(Object.keys(MODELS)[0]);
  const [perDay, setPerDay] = useStateA2(500);

  const q = QUERIES[query];
  const price = MODELS[model];
  const grepBytes = Math.round((files / 1000) * q.grepPerKFile);
  const crabccBytes = q.crabcc;
  const grepTok = Math.round(grepBytes / 4);
  const crabccTok = Math.round(crabccBytes / 4);
  const reduction = grepBytes > 0 ? (1 - crabccBytes / grepBytes) : 0;
  const savedPerQ = (grepTok - crabccTok) / 1e6 * price;
  const savedMonth = savedPerQ * perDay * 30;
  const fmt$ = (v) => v >= 1 ? "$" + v.toLocaleString(undefined, { maximumFractionDigits: 0 }) : "$" + v.toFixed(2);
  const fmtTok = (v) => v >= 1000 ? (v / 1000).toFixed(1).replace(/\.0$/, "") + "k" : String(v);
  const barCrab = Math.max(1.5, (crabccBytes / grepBytes) * 100);

  return (
    <section className="section section--tight" id="calc">
      <div className="wrap">
        <Head
          eyebrow="token economy · interactive"
          title="What grep is costing you"
          sub="Every grep dump is tokens you pay for and context you burn. Size it to your repo and your model — the numbers are bytes on the wire, turned into tokens at ~4 bytes each."
        />
        <div className="calc">
          <div className="calc__controls">
            <label className="calc__ctl">
              <span className="calc__ctl-h">repo size <b>{files.toLocaleString()} files</b></span>
              <input type="range" min="500" max="50000" step="500" value={files} onChange={(e) => setFiles(+e.target.value)} className="calc__range" />
            </label>
            <label className="calc__ctl">
              <span className="calc__ctl-h">the question</span>
              <Select fullWidth value={query} onChange={(e) => setQuery(e.target.value)} options={Object.keys(QUERIES)} />
            </label>
            <label className="calc__ctl">
              <span className="calc__ctl-h">model</span>
              <Select fullWidth value={model} onChange={(e) => setModel(e.target.value)} options={Object.keys(MODELS)} />
            </label>
            <label className="calc__ctl">
              <span className="calc__ctl-h">queries / day <b>{perDay.toLocaleString()}</b></span>
              <input type="range" min="10" max="5000" step="10" value={perDay} onChange={(e) => setPerDay(+e.target.value)} className="calc__range" />
            </label>
          </div>
          <div className="calc__out">
            <div className="calc__bars">
              <div className="calc__bar-row">
                <span className="calc__bar-l">grep -rn</span>
                <div className="calc__track"><div className="calc__fill calc__fill--bad" style={{ width: "100%" }}></div></div>
                <span className="calc__bar-v">{fmtTok(grepTok)} tok</span>
              </div>
              <div className="calc__bar-row">
                <span className="calc__bar-l">crabcc</span>
                <div className="calc__track"><div className="calc__fill calc__fill--good" style={{ width: barCrab + "%" }}></div></div>
                <span className="calc__bar-v">{fmtTok(crabccTok)} tok</span>
              </div>
            </div>
            <div className="calc__stats">
              <div className="calc__stat">
                <div className="calc__stat-n">−{Math.round(reduction * 100)}<span className="unit">%</span></div>
                <div className="calc__stat-l">tokens per query</div>
              </div>
              <div className="calc__stat">
                <div className="calc__stat-n">{fmt$(savedMonth)}</div>
                <div className="calc__stat-l">saved / month</div>
              </div>
              <div className="calc__stat">
                <div className="calc__stat-n">{fmtTok(Math.round((grepTok - crabccTok) * perDay * 30))}</div>
                <div className="calc__stat-l">tokens / month back</div>
              </div>
            </div>
            <p className="calc__fine">est. input-token pricing · grep byte counts modeled from real query traces · the point isn't the exact dollar, it's the order of magnitude.</p>
          </div>
        </div>
      </div>
    </section>
  );
}

/* ---------- trust signals ---------- */
function Trust() {
  const { Badge } = window.CrabccDesignSystem_325a37;
  const artifacts = [
    { f: "crabcc-0.4.0-aarch64-apple-darwin.tar.gz", sha: "9f2a1c… e7b40d" },
    { f: "crabcc-0.4.0-x86_64-unknown-linux-gnu.tar.gz", sha: "3c8e77… 1a9f02" },
    { f: "crabcc-0.4.0-x86_64-pc-windows-msvc.zip", sha: "b14d50… 6cc8ef" },
  ];
  return (
    <section className="section section--tight" id="trust">
      <div className="wrap">
        <div className="trust">
          <div className="trust__head">
            <div>
              <span className="eyebrow">provenance</span>
              <h2 className="section__title">Signed, checksummed, verifiable</h2>
              <p className="section__sub">A tool whose audience is other agents has to be trustworthy by default. Every release is signed and every artifact carries a SHA-256 — verify before you run.</p>
            </div>
            <span className="trust__badge"><span className="trust__badge-dot"></span>minisign verified</span>
          </div>
          <div className="trust__table">
            <div className="trust__row trust__row--head">
              <span>artifact</span><span>sha256</span><span></span>
            </div>
            {artifacts.map((a) => (
              <div className="trust__row" key={a.f}>
                <code className="trust__f">{a.f}</code>
                <code className="trust__sha">{a.sha}</code>
                <Badge tone="ok" dot>signed</Badge>
              </div>
            ))}
          </div>
          <div className="trust__verify">
            <div className="trust__verify-h">verify</div>
            <pre className="trust__cmd"><span className="tk-prompt">$ </span><span className="tk-cmd">minisign -Vm crabcc-0.4.0-*.tar.gz -P </span><span className="tk-dim">RWQf6L…crabcc</span>{"\n"}<span className="tk-ok">Signature and comment signature verified</span>{"\n"}<span className="tk-prompt">$ </span><span className="tk-cmd">sha256sum -c crabcc-0.4.0.SHA256</span>{"\n"}<span className="tk-ok">crabcc: OK</span></pre>
          </div>
        </div>
      </div>
    </section>
  );
}

Object.assign(window, { AIBar, SectionCopy, TokenCalculator, Trust, PAGE_MD, SECTION_MD });
