// Selfhost browser regression for the reported PostHog MCP OAuth dead-end. A
// real Executor instance adds https://mcp.posthog.com/mcp, then starts the
// connection flow. The product guarantee: clicking Connect opens PostHog's
// OAuth authorization page through dynamic client registration, not the
// bring-your-own OAuth app picker with "Automatic setup unavailable".
import { randomBytes } from "node:crypto";

import { expect } from "@effect/vitest";
import { Effect } from "effect";
import { composePluginApi } from "@executor-js/api/server";
import { deriveMcpNamespace } from "@executor-js/plugin-mcp";
import { mcpHttpPlugin } from "@executor-js/plugin-mcp/api";
import { IntegrationSlug } from "@executor-js/sdk/shared";

import { scenario } from "../src/scenario";
import { Api, Browser, Target } from "../src/services";

const POSTHOG_MCP_URL = "https://mcp.posthog.com/mcp";
const api = composePluginApi([mcpHttpPlugin()] as const);

scenario(
  "MCP OAuth · PostHog starts OAuth from Add connection",
  { timeout: 180_000 },
  Effect.scoped(
    Effect.gen(function* () {
      const target = yield* Target;
      const browser = yield* Browser;
      const { client: makeApiClient } = yield* Api;
      const identity = yield* target.newIdentity();
      const client = yield* makeApiClient(api, identity);
      const displayName = `PostHog MCP ${randomBytes(3).toString("hex")}`;
      const slug = IntegrationSlug.make(deriveMcpNamespace({ name: displayName }));

      yield* Effect.gen(function* () {
        yield* browser.session(identity, async ({ page, step }) => {
          await step("Open the add-MCP flow pointed at PostHog", async () => {
            const addUrl = new URL("/integrations/add/mcp", target.baseUrl);
            addUrl.searchParams.set("url", POSTHOG_MCP_URL);
            await page.goto(addUrl.toString(), { waitUntil: "networkidle" });
            await page.getByText("How does this server authenticate?").waitFor({ timeout: 30_000 });
            await page.getByText("Method 1 · Detected").waitFor();
            await page.getByText("OAuth metadata is discovered from this server").waitFor();
          });

          await step("Add the PostHog MCP integration", async () => {
            await page.getByPlaceholder("e.g. Linear").fill(displayName);
            await page.getByRole("button", { name: "Add integration" }).click();
            await page.waitForURL(/\/integrations\/(?!add\b)[^/?]+$/, { timeout: 30_000 });
            const landedSlug = new URL(page.url()).pathname.split("/").filter(Boolean).at(-1);
            expect(landedSlug, "the add flow lands on the created integration").toBe(String(slug));
            await page.getByText("Connections").first().waitFor();
          });

          await step("Start OAuth from Add connection", async () => {
            await page.getByRole("button", { name: "Add connection" }).first().click();
            await page.getByRole("heading", { name: /Add connection/ }).waitFor();
            await page.getByRole("tab", { name: "OAuth" }).waitFor();

            const popupPromise = page.waitForEvent("popup", { timeout: 30_000 });
            await page.getByRole("button", { name: "Connect", exact: true }).click();
            const popup = await popupPromise;
            await popup.waitForURL(/^https:\/\/oauth\.posthog\.com\/oauth\/authorize\//, {
              timeout: 30_000,
            });
            await popup.waitForLoadState("domcontentloaded", { timeout: 30_000 });

            const authorizeUrl = new URL(popup.url());
            expect(authorizeUrl.origin, "OAuth opened PostHog's authorization host").toBe(
              "https://oauth.posthog.com",
            );
            expect(authorizeUrl.pathname, "OAuth opened the authorize endpoint").toBe(
              "/oauth/authorize/",
            );
            expect(
              authorizeUrl.searchParams.get("resource"),
              "resource targets the MCP endpoint",
            ).toBe(POSTHOG_MCP_URL);
            await popup.close();
          });
        });
      }).pipe(Effect.ensuring(client.mcp.removeServer({ params: { slug } }).pipe(Effect.ignore)));
    }),
  ),
);
