/**
 * KHAELOR
 * File: prototypes/tui-spike/driver/debug-ink-input.tsx
 * Description: Diagnostic harness — traces stdin arrival vs Ink useInput delivery vs echo-frame
 *              write time, to attribute candidate B's measured input latency (skew vs real stall).
 *
 * Author: Simon-Pierre Boucher
 * Contact: contact@spboucher.ai
 */

import fs from "node:fs";
import React, { useEffect, useReducer, useState } from "react";
import { Box, Static, Text, render, useApp, useInput } from "ink";
import { DemoModel } from "../shared/demo";

const log: string[] = [];
const t0 = process.hrtime.bigint();
const ms = () => Number(process.hrtime.bigint() - t0) / 1e6;

const model = new DemoModel();

process.stdin.on("data", (b: Buffer) => {
  log.push(`${ms().toFixed(1)} DATA ${JSON.stringify(b.toString("utf8"))}`);
});

const origWrite = process.stdout.write.bind(process.stdout);
let lastComposer = "";
(process.stdout as unknown as { write: unknown }).write = (chunk: unknown, ...rest: unknown[]) => {
  const s = typeof chunk === "string" ? chunk : Buffer.from(chunk as Uint8Array).toString("utf8");
  if (lastComposer.length > 0 && s.includes("❯ " + lastComposer)) {
    log.push(`${ms().toFixed(1)} ECHO ${JSON.stringify(lastComposer.slice(-8))}`);
    lastComposer = "";
  }
  return (origWrite as (c: unknown, ...r: unknown[]) => boolean)(chunk, ...rest);
};

function App(): React.JSX.Element {
  const { exit } = useApp();
  const [settled, setSettled] = useState<{ id: number; text: string }[]>([]);
  const [, force] = useReducer((x: number) => x + 1, 0);

  useEffect(() => {
    model.on("settled", (lines: string[]) =>
      setSettled((s) => [...s, { id: s.length, text: lines.join("\n") }]),
    );
    model.on("dirty", () => force());
    const ticker = setInterval(() => {
      if (model.status !== null) force();
    }, 100);
    model.start();
    return () => clearInterval(ticker);
  }, []);

  useInput((input, key) => {
    log.push(
      `${ms().toFixed(1)} USEINPUT ${JSON.stringify(input)} esc=${key.escape} ret=${key.return}`,
    );
    if (key.escape) {
      exit();
      return;
    }
    if (key.return) {
      model.handleKey({ type: "enter" });
      log.push(`${ms().toFixed(1)} ENTER composer_now=${JSON.stringify(model.composer)}`);
      return;
    }
    for (const ch of input) model.handleKey({ type: "char", ch });
    lastComposer = model.composer;
    log.push(`${ms().toFixed(1)} COMPOSER ${JSON.stringify(model.composer.slice(-12))}`);
  });

  const snap = model.snapshot();
  const tail = snap.tail.length > 0 ? snap.tail.split("\n").slice(-12) : [];
  return (
    <>
      <Static items={settled}>{(i) => <Text key={i.id}>{i.text}</Text>}</Static>
      <Box flexDirection="column">
        {tail.length > 0 && <Text>{tail.join("\n")}</Text>}
        <Text>{"❯ " + snap.composer}</Text>
      </Box>
    </>
  );
}

const inst = render(<App />, { exitOnCtrlC: true, patchConsole: false });
setTimeout(() => inst.unmount(), Number(process.env.DURATION_MS ?? 6000)).unref();
await inst.waitUntilExit();
model.stop();
fs.writeFileSync(process.env.DEBUG_OUT ?? "out/debug-ink.log", log.join("\n") + "\n");
process.exit(0);
