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

// Give the free replay agent one synthetic turn that publishes through the real MCP tool.
function installHtmlReplay() {
  const path = `${APP_DIR}/apps/server/scripts/dev-replay-agent.ts`;
  let source = readFileSync(path, "utf8");
  source = source.replace('import * as NodeCrypto', 'import { execFileSync } from "node:child_process";\nimport * as NodeCrypto');
  source = source.replace('const sessions = new Map<', 'let proofServers: any[] = [];\n  const sessions = new Map<');
  source = source.replace('sessions.set(sessionId, { cwd,', 'proofServers = params.mcpServers as any[];\n        sessions.set(sessionId, { cwd,');
  source = source.replace('const turns = loadTurns(session.model);', `
        const server = proofServers.find((s) => s.name === "t3-code");
        const env = Object.fromEntries((server.env ?? []).map((e: any) => [e.name, e.value]));
        const output = JSON.parse(execFileSync(process.execPath, [new URL("../src/bin.ts", import.meta.url).pathname, "acp-mcp-call", "html_render", JSON.stringify({html: '<!doctype html><html><body style="margin:0;padding:40px;font:20px Arial;background:#f4f7fb;color:#182536"><h1 style="font-size:26px">A quiet workspace</h1><p style="display:inline-block;white-space:nowrap">A clear desk makes room for new ideas.</p><p style="font-size:16px">Select the sentence above and cite it in your reply.</p></body></html>', title: "Workspace mockup", height: 260})], {env: {...process.env, ...env}, encoding: "utf8"}));
        send({method:"session/update",params:{sessionId,update:{sessionUpdate:"tool_call",toolCallId:"proof-html",kind:"other",title:"t3-code.html_render",status:"completed",rawInput:{title:"Workspace mockup"},rawOutput:output,content:[{type:"content",content:{type:"text",text:JSON.stringify(output.structuredContent ?? output)}}]}}});
        send({method:"session/update",params:{sessionId,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:"The workspace mockup is ready."}}}});
        return {stopReason:"end_turn"};
        const turns = loadTurns(session.model);`);
  writeFileSync(path, source);
}

test("Cite a sentence selected inside a newly published HTML render", WEB, async ({ t3, app, screen, browser }) => {
  installHtmlReplay();
  await browser.setViewport({ width: 1440, height: 1000 });
  const project = await t3.project("Workspace demo");
  await t3.thread({ project, title: "HTML citation proof", model: "showcase", messages: ["Create an HTML mockup containing selectable text and publish it inline."] });
  await t3.open();
  await screen.getByRole("button", "HTML citation proof, Done, Workspace demo", {exact:true}).tap();
  const sentence = browser.frameLocator('iframe').getByText("A clear desk makes room for new ideas.", {exact:true});
  await sentence.waitFor({ timeout: 120000 });
  await sentence.scrollIntoView();
  const box = await sentence.boundingBox();
  if (!box) throw new Error("HTML sentence has no geometry");
  await browser.mouse.move(box.x + 1, box.y + box.height / 2);
  await browser.mouse.down();
  for (let i = 1; i <= 25; i++) await browser.mouse.move(box.x + box.width * i / 25, box.y + box.height / 2);
  await browser.mouse.up();
  const cite = screen.getByRole("button", "Cite selection in composer", { exact: true });
  try { await expect(cite).toBeVisible(); } finally { await app.screenshot("selected-html-sentence"); }
  await cite.tap();
  const chip = browser.locator('[data-composer-citation-chip]');
  await expect(chip).toBeVisible();
  await app.screenshot("quote-in-composer");
  await screen.getByRole("link", /View cited assistant text:/).tap();
  await browser.waitForURL(/#assistant-citation=/);
  await sentence.waitFor();
  await expect(screen.getByText("The quoted text has changed", {exact:true})).toBeHidden();
  await app.screenshot("citation-source");
});
