import { expect } from "e2e";
import { test, WEB } from "./t3.ts";

test("A background settle cannot redirect a stationary pointer to Thread D", WEB, async ({ t3, app, browser }) => {
  const project = await t3.project("Sidebar click demo");
  for (const letter of ["E", "D", "C", "B", "A"]) {
    await t3.thread({ project, title: `Thread ${letter}`, messages: ["Reply with a short greeting."] });
  }
  await browser.emulateMedia({ colorScheme: "dark" });
  await t3.open();
  const row = (title: string) => browser.locator(`[data-thread-item]`).filter({ hasText: title });
  await row("Thread C").getByRole("button", "Settle thread").waitFor({ state: "attached" });
  await browser.evaluate(async () => {
    const other = window.open(location.href, "background-settle");
    if (!other) throw new Error("Second tab did not open");
    Object.assign(window, { settleTab: other });
    await new Promise<void>((resolve, reject) => {
      const started = Date.now();
      const timer = setInterval(() => {
        if ([...other.document.querySelectorAll("[data-thread-item]")].some(el => el.textContent?.includes("Thread A"))) {
          clearInterval(timer); resolve();
        } else if (Date.now() - started > 30000) { clearInterval(timer); reject(new Error("Second tab did not load threads")); }
      }, 100);
    });
  });
  const point = await browser.evaluate(() => {
    const row = [...document.querySelectorAll("[data-thread-item]")].find(el => el.textContent?.includes("Thread C"));
    const button = row?.querySelector('[aria-label="Settle thread"]');
    if (!button) throw new Error("Thread C has no settle button");
    const box = button.getBoundingClientRect();
    return { x: box.x + box.width / 2, y: box.y + box.height / 2 };
  });
  await browser.mouse.move(point.x, point.y);
  await app.screenshot("pointer-aimed-at-C");
  // Let all earlier user input age out before the other tab's background update.
  await browser.evaluate(() => new Promise(resolve => setTimeout(resolve, 650)));
  await browser.evaluate(async ({ x, y }) => {
    const other = (window as unknown as { settleTab: Window }).settleTab;
    const a = [...other.document.querySelectorAll("[data-thread-item]")].find(el => el.textContent?.includes("Thread A"));
    const button = a?.querySelector<HTMLButtonElement>('[aria-label="Settle thread"]');
    if (!button) throw new Error("Second tab has no Thread A settle button");
    await new Promise<void>((resolve, reject) => {
      const observer = new MutationObserver(() => {
        if (document.elementFromPoint(x, y)?.closest("[data-thread-item]")?.textContent?.includes("Thread D")) {
          observer.disconnect(); clearTimeout(timeout); resolve();
        }
      });
      const timeout = setTimeout(() => { observer.disconnect(); reject(new Error("Thread D never shifted beneath the pointer")); }, 10000);
      observer.observe(document.body, { childList: true, subtree: true, attributes: true });
      button.click();
    });
  }, point);
  await browser.mouse.down();
  await browser.mouse.up();
  await browser.evaluate(() => new Promise(resolve => setTimeout(resolve, 650)));
  await app.screenshot("after-displaced-click");
  await expect(row("Thread D").getByRole("button", "Settle thread")).toBeVisible();
  await row("Thread D").getByRole("button", "Settle thread").tap();
  await app.screenshot("fresh-click-works");
  await expect(row("Thread D").getByRole("button", "Settle thread")).toBeHidden();
  await browser.evaluate(() => (window as unknown as { settleTab: Window }).settleTab.close());
});
