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

test("Composer keeps same-number reviews from GitHub and GitLab", WEB, async ({ t3, app, browser, screen }) => {
  const project = await t3.project("review-suggestions");
  execFileSync("git", ["remote", "add", "origin", "https://github.com/wireshark/wireshark.git"], { cwd: project });
  const thread = await t3.thread({ project, title: "Cross-host reviews", messages: ["Ready to review"] });
  await t3.open(thread);
  await browser.evaluate(async ({ threadId }) => {
    const descriptor = await fetch("/.well-known/t3/environment").then(r => r.json());
    const socket = new WebSocket(`${location.origin.replace(/^http/, "ws")}/ws?orchestrationProtocol=${descriptor.orchestrationProtocolVersion}`);
    await new Promise<void>((resolve, reject) => { socket.onopen = () => resolve(); socket.onerror = () => reject(new Error("RPC socket failed")); });
    const dispatch = (payload: Record<string, unknown>) => new Promise<void>((resolve, reject) => {
      const id = crypto.randomUUID();
      const receive = (event: MessageEvent) => {
        const messages = JSON.parse(event.data);
        for (const message of Array.isArray(messages) ? messages : [messages]) {
          if (message.requestId !== id) continue;
          if (message._tag === "Exit") {
            socket.removeEventListener("message", receive);
            if (message.exit._tag === "Success") resolve(); else reject(new Error(JSON.stringify(message)));
          }
        }
      };
      socket.addEventListener("message", receive);
      socket.send(JSON.stringify({ _tag: "Request", id, tag: "orchestration.dispatchCommand", payload: { ...payload, threadId, commandId: crypto.randomUUID() }, headers: [] }));
    });
    for (const [host, url, title] of [
      ["github.com", "https://github.com/wireshark/wireshark/pull/1", "Wireshark GitHub review"],
      ["gitlab.com", "https://gitlab.com/wireshark/wireshark/-/merge_requests/1", "Wireshark GitLab review"],
    ]) {
      const key = { host, repository: "wireshark/wireshark", number: 1 };
      await dispatch({ type: "thread.pull-request.link", ...key, url, source: "manual" });
      await dispatch({ type: "thread.pull-request-link.sync", ...key, snapshot: { state: "open", title, headBranch: "review", baseBranch: "main", isDraft: false, updatedAt: "2026-11-01T00:00:00.000Z", syncedAt: new Date().toISOString() }, stack: null });
    }
    socket.close();
    return true;
  }, thread);
  await screen.getByText("Show 1 more", { exact: true }).tap();
  const editor = screen.getByTestId("composer-editor");
  await editor.fill("#1");
  await screen.getByRole("option").first().waitFor({ state: "visible" });
  await app.screenshot("numeric-cross-host-suggestions");
  await editor.fill("#wireshark");
  await screen.getByRole("option").first().waitFor({ state: "visible" });
  await app.screenshot("text-cross-host-suggestions");
  await editor.fill("#1");
  await expect(screen.getByRole("option")).toHaveCount(2);
  await screen.getByRole("option").filter({ hasText: "Wireshark GitHub review" }).tap();
  await screen.getByRole("button", /Wireshark GitHub review$/).hover();
  await app.screenshot("github-selected-context");
  const githubUrls = await browser.evaluate(async () => {
    const { useComposerDraftStore } = await import("/src/composerDraftStore.ts");
    return Object.values(useComposerDraftStore.getState().draftsByThreadKey).flatMap(draft => draft.reviewComments.map(comment => comment.pullRequest?.url ?? ""));
  });
  console.log("Selected GitHub draft URLs:", JSON.stringify(githubUrls));
  expect(githubUrls).toContain("https://github.com/wireshark/wireshark/pull/1");
  await editor.fill("");
  await editor.fill("#1");
  await screen.getByRole("option").filter({ hasText: "Wireshark GitLab review" }).tap();
  await screen.getByRole("button", /Wireshark GitLab review$/).hover();
  await app.screenshot("gitlab-selected-context");
  const gitlabUrls = await browser.evaluate(async () => {
    const { useComposerDraftStore } = await import("/src/composerDraftStore.ts");
    return Object.values(useComposerDraftStore.getState().draftsByThreadKey).flatMap(draft => draft.reviewComments.map(comment => comment.pullRequest?.url ?? ""));
  });
  console.log("Selected GitLab draft URLs:", JSON.stringify(gitlabUrls));
  expect(gitlabUrls).toContain("https://gitlab.com/wireshark/wireshark/-/merge_requests/1");
});
