import { expect } from "e2e";
import { test, WEB } from "./t3.ts";
import { APP_DIR, T3_HOME } from "../e2e.config.ts";
import { spawn, execFileSync } from "node:child_process";
import { mkdirSync, writeFileSync, readFileSync } from "node:fs";
import { createServer } from "node:net";

const cli = (home: string, args: string[]) => execFileSync(process.execPath, ["apps/server/src/bin.ts", ...args, "--base-dir", home], {cwd:APP_DIR, encoding:"utf8", env:{...process.env,T3CODE_DEV_SEED:"0"}});

test("Externally linked environment appears when Settings opens", WEB, async ({t3,app,screen,browser}) => {
  const project = await t3.project("demo");
  const thread = await t3.thread({project,title:"Link refresh demonstration",messages:["first"]});
  await t3.open("/settings/labs");
  await screen.getByRole("switch", "Linked environments").tap();
  // Navigate with the app, keeping the mounted composer and its shared list alive.
  await screen.getByRole("button", "Close", {exact:true}).tap();
  await t3.open(thread);
  await app.screenshot("001-composer-before-external-link");
  const home = `${T3_HOME}/peer`;
  mkdirSync(`${home}/userdata`,{recursive:true});
  writeFileSync(`${home}/userdata/settings.json`,JSON.stringify({linkedEnvironmentsEnabled:true,environmentLabel:"Evidence peer"}));
  const port = await new Promise<number>(resolve=>{const s=createServer();s.listen(0,"127.0.0.1",()=>{const p=(s.address() as any).port;s.close(()=>resolve(p));});});
  const peer=spawn(process.execPath,["apps/server/src/bin.ts","serve","--base-dir",home,"--host","127.0.0.1","--port",String(port)],{cwd:APP_DIR,env:{...process.env,T3CODE_DEV_SEED:"0",T3CODE_AUTO_BOOTSTRAP_PROJECT_FROM_CWD:"0",PATH:`${T3_HOME}/bin:${process.env.PATH}`},stdio:["ignore","pipe","pipe"]});
  try {
    peer.stdout.resume(); peer.stderr.resume();
    for (let attempt=0;;attempt++) {
      try { const response=await fetch(`http://127.0.0.1:${port}/.well-known/t3/environment`); if(response.ok) break; } catch {}
      if(attempt>=120) throw new Error("Peer did not start");
      await new Promise(r=>setTimeout(r,250));
    }
    const token=/Token:\s*(\S+)/.exec(cli(home,["pair"]))?.[1];
    if(!token) throw new Error("No peer pairing token");
    cli(T3_HOME,["environment","link",`http://127.0.0.1:${port}`,"--pairing-code",token,"--access","full-access"]);
    await screen.getByRole("button", "Settings").tap();
    await screen.getByRole("button", "Environments",{exact:true}).tap();
    await expect.soft(screen.getByText("Full access · Reachable",{exact:true})).toBeVisible();
    await app.screenshot("002-open-panel-after-external-link");
    await new Promise(r=>setTimeout(r,11000));
    await browser.evaluate(()=>{window.dispatchEvent(new Event("blur"));window.dispatchEvent(new Event("focus"));document.dispatchEvent(new Event("visibilitychange"));});
    await screen.getByRole("button", "Close", {exact:true}).tap();
    await screen.getByRole("button", "Settings").tap();
    await screen.getByRole("button", "Environments", {exact:true}).tap();
    await expect.soft(screen.getByText("Full access · Reachable",{exact:true})).toBeVisible();
    await app.screenshot("003-return-to-panel");
    await browser.reload();
    await expect.soft(screen.getByText("Full access · Reachable",{exact:true})).toBeVisible();
    await app.screenshot("004-reload-control");
  } finally {peer.kill("SIGTERM");await new Promise<void>(r=>{if(peer.exitCode!==null)r();else peer.once("exit",()=>r());});}
});
