import { createServer } from "node:http";
import { expect } from "e2e";
import { test, WEB } from "./t3.ts";

test("Stop cancels partial and pre-header navigation; idle Refresh reloads", WEB, async ({ t3, app, screen, browser }) => {
  const counts = { partial: 0, delayed: 0, normal: 0 };
  const log: string[] = [];
  const started = { partial: Promise.withResolvers<void>(), delayed: Promise.withResolvers<void>(), normal: Promise.withResolvers<void>() };
  const server = createServer((req, res) => {
    const path = req.url?.split("?")[0];
    if (path === "/observe") {
      setTimeout(() => res.end(JSON.stringify(counts)), 1500);
      return;
    }
    if (path === "/favicon.ico") { res.writeHead(204).end(); return; }
    const kind = path === "/partial" ? "partial" : path === "/delayed" ? "delayed" : "normal";
    counts[kind]++;
    started[kind].resolve();
    log.push(`${kind}: request ${counts[kind]}`);
    req.on("close", () => log.push(`${kind}: connection closed`));
    if (kind === "delayed") return;
    res.writeHead(200, { "content-type": "text/html; charset=utf-8", "cache-control": "no-store" });
    res.write(`<html><head><title>Stop navigation proof</title></head><body style="font:20px system-ui;padding:28px;background:#edf5f8;color:#102733"><h1>${kind === "partial" ? "Partial HTML — response held open" : "Normal page — response complete"}</h1><h2>${kind} request #${counts[kind]}</h2><p>Stop should close the request without a replacement.</p><pre>${log.join("\n")}</pre>`);
    if (kind === "normal") res.end("</body></html>");
  });
  await new Promise<void>((resolve) => server.listen(0, "127.0.0.1", resolve));
  const port = (server.address() as { port: number }).port;
  const origin = `http://127.0.0.1:${port}`;
  const observe = async () => (await fetch(`${origin}/observe`)).json();
  try {
    const project = await t3.project("Browser cancellation proof");
    const thread = await t3.thread({ project, title: "Stop loading demonstration", messages: ["Prepare browser navigation proof"] });
    await t3.open(thread);
    await screen.getByRole("button", "Toggle right panel").tap();
    await screen.getByRole("button", "Browser B").tap();
    const address = screen.getByRole("textbox", "Search or enter URL");
    const navigate = async (path: string) => {
      await address.fill(`${origin}/${path}`);
      await browser.keyboard.press("Enter");
    };
    await navigate("partial");
    await started.partial.promise;
    await screen.getByRole("button", "Stop").tap();
    const partial = await observe();
    await app.screenshot("partial-after-stop");
    expect.soft(partial.partial).toBe(1);
    await expect.soft(screen.getByRole("button", "Refresh")).toBeVisible({ timeout: 3000 });

    await screen.getByRole("button", "Add panel surface").tap();
    await screen.getByRole("menuitem", "Browser B").tap();
    await navigate("delayed");
    await started.delayed.promise;
    await screen.getByRole("button", "Stop").tap();
    const delayed = await observe();
    await app.screenshot("pre-header-after-stop");
    expect.soft(delayed.delayed).toBe(1);
    await expect.soft(screen.getByRole("button", "Refresh")).toBeVisible({ timeout: 3000 });
    await expect.soft(address).toHaveValue("", { timeout: 3000 });
    await expect.soft(screen.getByRole("heading", "This site can’t be reached")).not.toBeVisible();

    await navigate("normal");
    await started.normal.promise;
    await observe();
    await screen.getByRole("button", "Refresh").tap();
    const normal = await observe();
    await app.screenshot("idle-refresh-request-log");
    expect(normal.normal).toBe(2);
  } finally {
    server.closeAllConnections();
    await new Promise<void>((resolve) => server.close(() => resolve()));
  }
});
