/// <reference lib="dom" />
import { expect } from "e2e";
import { writeFileSync } from "node:fs";
import { test, WEB } from "./t3.ts";

test("Terminal delimiter hover latency", WEB, async ({ t3, app, browser, screen }) => {
  const url = "https://example.com/docs/page(v2)";
  const project = await t3.project("terminal-demo", {
    "paren.txt": url + ")".repeat(6000) + "\n",
    "control.txt": url + "a".repeat(6000) + "\n",
  });
  const thread = await t3.thread({ project, title: "Terminal link performance", messages: ["Ready"] });
  await t3.open(thread);
  await screen.getByRole("button", "Toggle terminal drawer").tap();
  await browser.locator("[data-thread-terminal-drawer] canvas").tap();
  await browser.evaluate(() => {
    // Keep every wrapped row visible in the runner's 1920x1280 viewport.
    document.querySelector("[data-thread-terminal-drawer]").style.height = "1050px";
  });
  const results = [];
  for (const file of ["paren.txt", "control.txt"]) {
    await browser.locator("[data-thread-terminal-drawer] canvas").tap();
    await browser.keyboard.type(`PS1=""; clear; cat ${file}; echo`);
    await browser.keyboard.press("Enter");
    await browser.evaluate(() => new Promise(resolve => setTimeout(() => resolve(null), 700)));
    const point = await browser.evaluate(() => {
      const canvas = document.querySelector("[data-thread-terminal-drawer] canvas");
      const b = canvas.getBoundingClientRect();
      return {x:b.x + 24, y:b.y + 12};
    });
    for (let run = 0; run < 5; run++) {
      await browser.mouse.move(point.x, point.y - 25);
      await browser.evaluate(() => {
        window.__perf = { tasks: [], frames: [] };
        window.__observer = new PerformanceObserver(list => window.__perf.tasks.push(...list.getEntries().map(e => e.duration)));
        window.__observer.observe({type: "longtask"});
        window.__listener = () => { const start = performance.now(); requestAnimationFrame(() => requestAnimationFrame(() => window.__perf.frames.push(performance.now() - start))); };
        document.addEventListener("pointermove", window.__listener, true);
      });
      for (let pass = 0; pass < 8; pass++) for (let move = 0; move < 7; move++) {
        await browser.mouse.move(point.x + (pass % 2 ? 6 - move : move) * 15, point.y);
        await browser.evaluate(() => new Promise(resolve => requestAnimationFrame(() => requestAnimationFrame(resolve))));
      }
      const measurement = await browser.evaluate(() => {
        window.__observer.disconnect(); document.removeEventListener("pointermove", window.__listener, true);
        return window.__perf;
      });
      results.push({file, run, ...measurement});
    }
    await app.screenshot(file.replace(".txt", "-hover"));
  }
  const parser = await browser.evaluate(async () => {
    const {extractTerminalLinks} = await import(/* @vite-ignore */ "/src/terminal-links.ts");
    return [0,5000,6000,10000].map(count => {
      const text = "https://example.com/docs/page(v2)" + ")".repeat(count);
      const times = []; let links;
      for(let i=0;i<7;i++) {const start=performance.now(); links=extractTerminalLinks(text); times.push(performance.now()-start);}
      return {count,times,links};
    });
  });
  const report = { browser: await browser.evaluate(() => navigator.userAgent), viewport: {width:1920,height:1280}, results, parser };
  console.log("MEASUREMENT " + JSON.stringify(report));
  writeFileSync(`${process.env.EVIDENCE_OUTPUT_DIR ?? "."}/measurement-${Date.now()}.json`, JSON.stringify(report,null,2));
  const med = a => [...a].sort((a,b)=>a-b)[Math.floor(a.length/2)];
  await expect(med(results.filter(r=>r.file==="paren.txt").map(r=>med(r.frames)))).toBeLessThan(100);
});
