import { expect } from "e2e";
import * as NodeCrypto from "@effect/platform-node/NodeCrypto";
import * as NetService from "@t3tools/shared/Net";
import * as Effect from "effect/Effect";
import * as Layer from "effect/Layer";
import * as Option from "effect/Option";
import * as References from "effect/References";
import * as EnvironmentAuth from "../../apps/server/src/auth/EnvironmentAuth.ts";
import * as ServerConfig from "../../apps/server/src/config.ts";
import { resolveCliAuthConfig } from "../../apps/server/src/cli/config.ts";
import { mcpToolSession } from "../../apps/server/src/mcp/AcpMcpStdioBridge.ts";
import { readLiveServerRuntimeState } from "../../apps/server/src/serverRuntimeState.ts";
import { T3_HOME } from "../e2e.config.ts";
import { test, WEB, runPromise } from "./t3.ts";

const title = "Retry webhook deliveries after a timeout";
async function launchIdle() {
  return runPromise(Effect.gen(function* () {
    const config = yield* resolveCliAuthConfig({ baseDir: Option.some(T3_HOME) }, Option.none());
    return yield* Effect.gen(function* () {
      const runtime = yield* readLiveServerRuntimeState(config.serverRuntimeStatePath);
      if (Option.isNone(runtime)) throw new Error("Scenario server is not running");
      const auth = yield* EnvironmentAuth.EnvironmentAuth;
      const issued = yield* Effect.acquireRelease(
        auth.issueMcpClientSession({ label: "Scenario", access: "full-access", peerLink: false, client: { deviceType: "bot" } }),
        session => auth.revokeSession(session.sessionId),
      );
      const session = yield* mcpToolSession({ endpoint: new URL("/mcp", runtime.value.origin).href, authorization: `Bearer ${issued.token}`, clientName: "scenario" });
      const projects = yield* session.call("t3_project_list", { limit: 100 });
      const projectId = projects.structuredContent.projects[0].id;
      const launched = yield* session.call("t3_thread_launch", { projectId, title, modelSelection: { instanceId: "devReplay", model: "showcase" } });
      if (launched.isError || launched.structuredContent.runId !== null) throw new Error("Idle launch failed");
      return { threadId: launched.structuredContent.threadId };
    }).pipe(Effect.scoped, Effect.provide(EnvironmentAuth.layerRuntime.pipe(Layer.provide(ServerConfig.layer(config)), Layer.provide(Layer.succeed(References.MinimumLogLevel, config.logLevel)))));
  }).pipe(Effect.provide([NetService.layer, NodeCrypto.layer])));
}

test("An idle launched thread keeps its deliberate title on its first message", WEB, async ({ t3, app, screen }) => {
  await t3.project("Webhook demo");
  const thread = await launchIdle();
  await t3.open(thread);
  await screen.getByText("Send a message to start the conversation.", { exact: true }).waitFor({ state: "visible" });
  await screen.getByRole("textbox").fill("work on this");
  await app.screenshot("named-idle-thread");
  await screen.getByRole("textbox").press("Enter");
  await screen.getByText("This turn is a replay.", { exact: false }).waitFor({ state: "visible" });
  await screen.getByRole("button", "Stop generation").waitFor({ state: "hidden" });
  await app.screenshot("title-after-first-message");
  await expect(screen.getByRole("button", `${title}, Webhook demo`, { exact: true })).toBeVisible();
});
