import { readFile, writeFile } from "node:fs/promises";
import { expect } from "e2e";
import { APP_DIR } from "../e2e.config.ts";
import { test, WEB } from "./t3.ts";

test("Everything announces an active context compaction", WEB, async ({ t3, app, screen, browser }) => {
  // Identical replay input on both commits; the app's adapter and UI remain real.
  const agent = `${APP_DIR}/apps/server/scripts/dev-replay-agent.ts`;
  const source = await readFile(agent, "utf8");
  await writeFile(agent, source.replace('const REPLAYED_UPDATES = new Set([', 'const REPLAYED_UPDATES = new Set(["compaction_update",'));
  const prompt = { type: "expect_outbound", frame: { kind: "request", method: "session/prompt", params: "<any>" } };
  const update = (value: object, afterMs = 2000) => ({type: "emit_inbound", afterMs, frame: {kind: "notification", method: "session/update", params: {sessionId: "replay", update: value}}});
  const frames = [prompt,
    update({sessionUpdate: "agent_message_chunk", content: {type: "text", text: "Ready."}}, 30),
    {type: "emit_inbound", frame: {kind: "response", method: "session/prompt", result: {stopReason: "end_turn"}}},
    prompt,
    update({sessionUpdate: "tool_call", toolCallId: "control", kind: "execute", title: "Running sleep", status: "in_progress", rawInput: {command: "sleep 4"}}),
    update({sessionUpdate: "tool_call_update", toolCallId: "control", status: "in_progress"}),
    update({sessionUpdate: "tool_call_update", toolCallId: "control", status: "completed"}),
    update({sessionUpdate: "compaction_update", compactionId: "compact", status: "in_progress"}),
    ...Array.from({length: 7}, () => update({sessionUpdate: "compaction_update", compactionId: "compact", status: "in_progress"})),
    update({sessionUpdate: "compaction_update", compactionId: "compact", status: "completed"}),
    update({sessionUpdate: "agent_message_chunk", content: {type: "text", text: "Done."}}),
    {type: "emit_inbound", frame: {kind: "response", method: "session/prompt", result: {stopReason: "end_turn"}}}];
  await writeFile(`${APP_DIR}/apps/server/scripts/dev-replay/showcase_transcript.ndjson`, frames.map(x => JSON.stringify(x)).join("\n"));
  const project = await t3.project("Compaction demo");
  await t3.thread({project, title: "Compaction announcement", model: "showcase", messages: ["Prepare context"]});
  await browser.addInitScript(() => localStorage.setItem("t3code:client-settings:v1", JSON.stringify({screenReaderAnnouncements: "everything"})));
  await t3.open();
  await browser.locator("[data-thread-item]").first().tap();
  await screen.getByRole("textbox").fill("Run sleep 4, then compact context, then reply done");
  await browser.evaluate(() => {
    const panel = document.createElement("pre");
    panel.id = "announcement-evidence";
    panel.style.cssText = "position:fixed;right:20px;top:70px;width:430px;min-height:120px;background:#111827;color:#fff;padding:18px;border:2px solid #60a5fa;z-index:99999;font:16px/1.6 monospace;white-space:pre-wrap";
    panel.textContent = "ARIA-LIVE WRITES · Everything\n";
    document.body.append(panel);
    new MutationObserver(records => {
      for (const record of records) {
        const el = record.target instanceof Element ? record.target : record.target.parentElement;
        const region = el?.closest("[aria-live]");
        const text = region?.textContent?.trim();
        if (text) panel.textContent += `${text}\n`;
      }
    }).observe(document.body, {subtree:true, childList:true, characterData:true});
  });
  await screen.getByRole("textbox").press("Enter");
  await screen.getByText("Compacting context", {exact: true}).first().waitFor({state:"visible"});
  await browser.evaluate(() => new Promise(resolve => setTimeout(resolve, 3500)));
  await app.screenshot("compaction-start");
  const spoken = await browser.evaluate(() => document.getElementById("announcement-evidence")?.textContent ?? "");
  expect(spoken).toContain("Compacting context");
});
