import { expect } from "e2e";
import { readFileSync, writeFileSync } from "node:fs";
import { join } from "node:path";
import { APP_DIR, T3_HOME } from "../e2e.config.ts";
import { test, WEB, makeState, runPromise } from "./t3.ts";

test("A kept fork retains Page A after deleting its source", WEB, async ({ t3, app, screen, browser }) => {
  // Teach the free replay agent to call the real HTML publishing tool on each turn.
  const agentPath = join(APP_DIR, "apps/server/scripts/dev-replay-agent.ts");
  const original = readFileSync(agentPath, "utf8");
  const patched = original.replace('name: "Multi turn"', 'name: "HTML pages"').replace('import * as NodeCrypto from "node:crypto";', 'import * as NodeCrypto from "node:crypto";\nimport { execFileSync } from "node:child_process";').replace(
    'if (turn !== undefined) ended = await playTurn(sessionId, turn, controller.signal);',
    `const page = session.promptCount === 1 ? "Page A" : "Page B";
    const html = '<!doctype html><html><body style="margin:0;padding:32px;background:#eef6ff;color:#123;font:20px system-ui"><h1>' + page + '</h1><p>' + (page === "Page A" ? "This inherited page must survive deleting its source." : "Published after the fork; belongs only to the source.") + '</p></body></html>';
    const toolCallId = NodeCrypto.randomUUID();
    const rawInput = {tool_id:"t3-code::html_render",arguments:{html,title:page,height:240}};
    const meta = {kiro:{serverName:"t3-code",toolOrigin:"default"}};
    send({method:"session/update",params:{sessionId,update:{sessionUpdate:"tool_call",toolCallId,title:"@t3-code/html_render",kind:"other",status:"pending",rawInput,_meta:meta}}});
    const raw = execFileSync(process.execPath, [new URL("../src/bin.ts", import.meta.url).pathname, "acp-mcp-call", "html_render", JSON.stringify({html,title:page,height:240})], {env:process.env,encoding:"utf8"});
    const result = JSON.parse(raw);
    if (result.isError) throw new Error(raw);
    send({method:"session/update",params:{sessionId,update:{sessionUpdate:"tool_call_update",toolCallId,title:"@t3-code/html_render",status:"completed",rawInput,rawOutput:result,content:[{type:"content",content:{type:"text",text:JSON.stringify(result.structuredContent ?? result)}}],_meta:meta}}});
    send({method:"session/update",params:{sessionId,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:page + " published."}}}});`
  );
  writeFileSync(agentPath, patched);
  try {
    const project = await t3.project("HTML fork demo");
    const state = makeState(T3_HOME);
    const cli = (args: string[]) => runPromise(state.cli(args));
    const started = await cli(["thread","start",project,"Publish Page A","--title","Page source","--provider","devReplay","--model","multi-turn","--wait","--json"]);
    const {threadId} = JSON.parse(started.stdout);
    await t3.open();
    await screen.getByRole("button", /^Page source,/).tap();
    await screen.getByRole("button","Fork from this response").tap();
    await screen.getByRole("button", /^Page source fork,/).tap();
    const forkUrl = await browser.url();
    await cli(["thread","send",threadId,"Publish Page B","--wait","--json"]);
    await app.screenshot("fork-before-source-deletion");
    await screen.getByRole("button", /^Page source,/).tap();
    await screen.getByRole("button","Thread actions for Page source").tap();
    await screen.getByRole("menuitem","Delete").tap();
    await screen.getByRole("button","Confirm",{exact:true}).tap();
    await browser.goto(forkUrl);
    await browser.reload();
    // Settle on either the rendered page or its user-visible failure before capturing.
    await browser.evaluate(async () => {
      await new Promise<void>((resolve) => {
        const ready = () => document.body.textContent?.includes("Unable to load Page A") || [...document.querySelectorAll("iframe")].some(f => f.contentDocument?.body?.textContent?.includes("This inherited page"));
        if (ready()) return resolve();
        const timer = setInterval(() => { if (ready()) { clearInterval(timer); resolve(); } },100);
        setTimeout(() => {clearInterval(timer);resolve();},20000);
      });
    });
    await app.screenshot("kept-fork-after-source-deletion");
    await expect(browser.frameLocator('iframe[title="Page A"]').getByText("This inherited page must survive deleting its source.")).toBeVisible();
  } finally {
    writeFileSync(agentPath, original);
  }
});
