import { expect } from "e2e";
import { DatabaseSync } from "node:sqlite";
import { setTimeout } from "node:timers/promises";
import { T3_HOME } from "../e2e.config.ts";
import { test, WEB } from "./t3.ts";

test("Archiving a destination stops its interval schedule", WEB, async ({ t3, app, screen, browser }) => {
  const project = await t3.project("Schedule demo");
  await t3.thread({ project, title: "Scheduled destination", messages: ["Hello"] });
  const db = new DatabaseSync(`${T3_HOME}/userdata/statev2.sqlite`, { readOnly: true });
  const row = db.prepare("SELECT thread_id, project_id FROM orchestration_v2_projection_threads WHERE title = ?").get("Scheduled destination") as { thread_id: string; project_id: string };
  db.close();
  await t3.open();
  await browser.waitForURL(/\/(?!pair)[^#]*$/);
  await app.open("/settings/scheduled-tasks");
  await browser.evaluate(async ({ threadId, projectId }) => {
    const socket = new WebSocket(`${location.origin.replace(/^http/, "ws")}/ws?orchestrationProtocol=2`);
    await new Promise<void>((resolve, reject) => { socket.onopen = () => resolve(); socket.onerror = () => reject(new Error("WebSocket failed")); });
    let serial = 0;
    const call = (tag: string, payload: unknown) => new Promise((resolve, reject) => {
      const id = String(++serial);
      const listener = (event: MessageEvent) => {
        const decoded = JSON.parse(event.data);
        for (const message of Array.isArray(decoded) ? decoded : [decoded]) {
          if (String(message.requestId) !== id || message._tag !== "Exit") continue;
          socket.removeEventListener("message", listener);
          if (message.exit._tag === "Success") resolve(message.exit.value);
          else reject(new Error(JSON.stringify(message.exit)));
        }
      };
      socket.addEventListener("message", listener);
      socket.send(JSON.stringify({ _tag: "Request", id, tag, payload, headers: [] }));
    });
    await call("scheduledTasks.upsert", {
      id: "schedule-archive-proof", title: "Archived destination check", prompt: "Check progress",
      enabled: true, schedule: { type: "interval", everyMs: 60000 }, projectId, threadId,
      workspaceStrategy: { type: "root" }, modelSelection: { instanceId: "devReplay", model: "multi-turn" },
      runtimeMode: "full-access", interactionMode: "default",
    });
    await call("orchestration.dispatchCommand", { type: "thread.archive", commandId: crypto.randomUUID(), threadId });
    socket.close();
    return true;
  }, { threadId: row.thread_id, projectId: row.project_id });
  // Observe the first real timer delivery, with no clock or database manipulation.
  await setTimeout(75000);
  await app.screenshot("archived-destination-after-due-time");
  await expect(screen.getByRole("switch", "Enable Archived destination check")).not.toBeChecked();
  await expect(screen.getByText("archived", { exact: false }).last()).toBeVisible();
});
