/**
 * E2E verification that REQUIRE_PLUGINS=1 fails the rollout via /healthcheck.
 *
 * The unit tests in @trigger.dev/rbac cover the loader throw. This file
 * closes the loop end-to-end: spawn a real webapp, hit /healthcheck via
 * HTTP, and verify the route's catch turns the throw into a 500 — the
 * status the ECS/k8s readiness probe rolls back on.
 *
 * Each case spawns its own webapp + Postgres + Redis container (~30s) so
 * env can differ per case. Slow but isolated, matching api-auth.e2e.test.ts.
 *
 * Requires a pre-built webapp: pnpm run build --filter webapp
 *
 * The REQUIRE_PLUGINS=1 case relies on the plugin NOT being resolvable
 * from the spawned webapp. CI satisfies this because the plugin isn't in
 * pnpm-lock.yaml. Local devs who ran `pnpm dev:link-webapp` have the
 * plugin symlinked into apps/webapp/node_modules — that case is detected
 * and skipped below.
 */
import { existsSync } from "node:fs";
import { resolve } from "node:path";
import { afterAll, beforeAll, describe, expect, it, vi } from "vitest";
import type { TestServer } from "@internal/testcontainers/webapp";
import { startTestServer } from "@internal/testcontainers/webapp";

const LINKED_PLUGIN_PATH = resolve(__dirname, "..", "node_modules", "@triggerdotdev", "plugins");
const pluginLocallyLinked = existsSync(LINKED_PLUGIN_PATH);

vi.setConfig({ testTimeout: 180_000 });

describe("/healthcheck with REQUIRE_PLUGINS", () => {
  describe.skipIf(pluginLocallyLinked)("REQUIRE_PLUGINS=1 + plugin missing", () => {
    let server: TestServer;

    beforeAll(async () => {
      // requirePlugins: true implies forceRbacFallback: false, so the
      // loader actually tries to dynamic-import the plugin. The plugin
      // is not installed in this OSS repo, so the import fails and the
      // loader throws (instead of falling back) because REQUIRE_PLUGINS=1.
      // The throw surfaces on the first .isUsingPlugin() call from the
      // /healthcheck route, which catches it and returns 500.
      server = await startTestServer({ requirePlugins: true });
    }, 180_000);

    afterAll(async () => {
      await server?.stop();
    }, 120_000);

    it("returns 500 so the readiness probe fails and the rollout is rolled back", async () => {
      const res = await server.webapp.fetch("/healthcheck");
      expect(res.status).toBe(500);
      expect(await res.text()).toBe("ERROR");
    });
  });

  // Surface the skip in dev so it doesn't go unnoticed. CI hits the real test above.
  describe.runIf(pluginLocallyLinked)(
    "REQUIRE_PLUGINS=1 + plugin LOCALLY LINKED (cross-repo dev setup)",
    () => {
      it.skip(`skipped because ${LINKED_PLUGIN_PATH} exists — plugin would load successfully. Run \`pnpm dev:unlink-webapp\` to exercise this case locally; CI runs it without the link.`, () => {});
    }
  );

  describe("REQUIRE_PLUGINS unset + plugin missing", () => {
    let server: TestServer;

    beforeAll(async () => {
      // Default: forceRbacFallback=true so the loader short-circuits to
      // the fallback without trying to import. /healthcheck succeeds.
      server = await startTestServer();
    }, 180_000);

    afterAll(async () => {
      await server?.stop();
    }, 120_000);

    it("returns 200 (baseline — unchanged self-hoster behaviour)", async () => {
      const res = await server.webapp.fetch("/healthcheck");
      expect(res.status).toBe(200);
      expect(await res.text()).toBe("OK");
    });
  });
});
