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

test("Queued scheduled deliveries follow each current model selection", WEB, async ({ t3, app, screen, browser }) => {
  async function startedDelivery(number: number) {
    return browser.evaluate(async ({ threadId, number }) => {
      const { appAtomRegistry } = await import("/src/rpc/atomRegistry.ts");
      const { environmentThreadDetails } = await import("/src/state/threads.ts");
      const environmentId = location.pathname.split("/")[1];
      const atom = environmentThreadDetails.threadAtom({ environmentId, threadId });
      return new Promise((resolve) => {
        let unsubscribe = () => {};
        const inspect = (value) => {
          const projection = value?.projection;
          if (!projection) return;
          const scheduled = projection.runs.filter((run) => projection.messages.some((message) => message.id === run.userMessageId && message.scheduledTaskId));
          const run = scheduled[number - 1];
          if (!run || ["queued", "preparing", "starting"].includes(run.status)) return;
          unsubscribe();
          resolve({ run: run.modelSelection.model, durable: projection.thread.modelSelection.model, provider: run.providerInstanceId });
        };
        unsubscribe = appAtomRegistry.subscribe(atom, inspect, { immediate: true });
      });
    }, { threadId: thread.threadId, number });
  }
  // Redact home paths in replay tool labels before the browser paints a capture.
  await browser.addInitScript(() => {
    const redact = () => {
      if (!document.body) return;
      const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT);
      while (walker.nextNode()) {
        const node = walker.currentNode;
        if (node.parentElement?.closest("script, style")) continue;
        const text = node.textContent ?? "";
        const safe = text.replace(/\/(?:home|Users)\/[^\s]+/g, "[workspace]");
        if (safe !== text) node.textContent = safe;
      }
    };
    new MutationObserver(redact).observe(document, { subtree: true, childList: true, characterData: true });
  });
  const project = await t3.project("scheduled-demo");
  const thread = await t3.thread({ project, title: "Scheduled model selection", model: "question", messages: ["Hold active work for scheduled deliveries"] });
  await t3.open(thread);
  await screen.getByRole("button", "Question", { exact: true }).waitFor();

  const task = await browser.evaluate(async (threadId) => {
    const { appAtomRegistry } = await import("/src/rpc/atomRegistry.ts");
    const { threadEnvironment } = await import("/src/state/threads.ts");
    const { serverEnvironment } = await import("/src/state/server.ts");
    const environmentId = location.pathname.split("/")[1];
    const snapshot = appAtomRegistry.get(threadEnvironment.snapshotAtom(environmentId));
    const shell = snapshot.threads.find((t) => t.id === threadId);
    const result = await serverEnvironment.upsertScheduledTask.run(appAtomRegistry, { environmentId, input: {
      title: "Model follow", prompt: "Report scheduled delivery", enabled: false,
      schedule: { type: "interval", everyMs: 86400000 }, projectId: shell.projectId, threadId,
      threadMode: "continue", workspaceStrategy: { type: "root" },
      modelSelection: { instanceId: "devReplay", model: "question" }, runtimeMode: "approval-required", interactionMode: "default", creationSource: "web"
    }});
    return JSON.parse(JSON.stringify(result));
  }, thread.threadId);
  if (task._tag !== "Success") throw new Error(JSON.stringify(task));
  await screen.getByRole("button", "Run Model follow now", { exact: true }).tap();
  await screen.getByRole("region", "1 queued message", { exact: true }).waitFor();
  await screen.getByRole("button", "Run Model follow now", { exact: true }).tap();
  await screen.getByRole("region", "2 queued messages", { exact: true }).waitFor();
  await app.screenshot("two-deliveries-queued-on-A");
  await screen.getByRole("button", "Stop generation", { exact: true }).tap();
  await screen.getByRole("button", "Send now", { exact: true }).first().waitFor();
  await screen.getByRole("button", "Question", { exact: true }).tap();
  await screen.getByRole("option", /^Showcase ,/).tap();
  await browser.keyboard.press("Escape");
  await screen.getByRole("dialog").waitFor({ state: "hidden" });
  await screen.getByRole("button", "Showcase", { exact: true }).waitFor();
  await app.screenshot("selected-B-before-first-delivery");
  await screen.getByRole("button", "Send now", { exact: true }).first().tap();
  const first = await startedDelivery(1);
  await screen.getByRole("button", "Stop generation", { exact: true }).waitFor();
  await screen.getByText(/Should this fixture prefer strict schemas|The project has a single math module/, { exact: false }).last().waitFor();
  await app.screenshot("first-delivery-model-B");
  await screen.getByRole("button", "Stop generation", { exact: true }).tap();
  await screen.getByRole("button", "Send now", { exact: true }).waitFor();
  await browser.locator("[data-chat-provider-model-picker]").tap();
  await screen.getByRole("option", /^Plan and reads ,/).tap();
  await browser.keyboard.press("Escape");
  await screen.getByRole("dialog").waitFor({ state: "hidden" });
  await screen.getByRole("button", "Plan and reads", { exact: true }).waitFor();
  await app.screenshot("selected-C-before-second-delivery");
  await screen.getByRole("button", "Send now", { exact: true }).tap();
  const second = await startedDelivery(2);
  await screen.getByText(/Should this fixture prefer strict schemas|todo list fixture complete/, { exact: false }).last().waitFor();
  await app.screenshot("second-delivery-model-C");
  console.log("DELIVERY_SELECTIONS", JSON.stringify({ first, second }));
  await expect({ first, second }).toEqual({
    first: { run: "showcase", durable: "showcase", provider: "devReplay" },
    second: { run: "todo-list", durable: "todo-list", provider: "devReplay" },
  });
});
