import {
  expect,
  type Page,
  type Route,
  type TestInfo,
  test,
} from "@playwright/test";

async function seedTokenLogin(page: Page): Promise<void> {
  await page.addInitScript(() => {
    window.localStorage.setItem("baron_auth_token", "e30.e30.e30");
    window.localStorage.setItem("baron_auth_provider", "ory");
    window.localStorage.removeItem("baron_auth_cookie_mode");
    window.localStorage.removeItem("baron_auth_pending_provider");
  });
}

async function mockInventoryApis(page: Page): Promise<void> {
  await page.route("**/api/v1/**", async (route: Route) => {
    const requestUrl = new URL(route.request().url());
    const path = requestUrl.pathname;
    const method = route.request().method().toUpperCase();

    if (path.endsWith("/api/v1/user/me")) {
      const authHeader = route.request().headers().authorization ?? "";
      if (authHeader.startsWith("Bearer ")) {
        await route.fulfill({
          status: 200,
          contentType: "application/json",
          body: JSON.stringify({
            id: "e2e-user",
            email: "e2e@example.com",
            name: "E2E User",
            phone: "+821012341234",
            department: "QA",
            affiliationType: "employee",
            companyCode: "BARON",
            tenant: {
              id: "tenant-1",
              name: "Baron",
              slug: "baron",
              description: "E2E tenant",
            },
          }),
        });
        return;
      }

      await route.fulfill({
        status: 401,
        contentType: "application/json",
        body: JSON.stringify({ error: "unauthorized" }),
      });
      return;
    }

    if (path.endsWith("/api/v1/user/rp/linked")) {
      await route.fulfill({
        status: 200,
        contentType: "application/json",
        body: JSON.stringify({ items: [] }),
      });
      return;
    }

    if (path.endsWith("/api/v1/audit/auth/timeline")) {
      await route.fulfill({
        status: 200,
        contentType: "application/json",
        body: JSON.stringify({ items: [], next_cursor: "" }),
      });
      return;
    }

    if (path.endsWith("/api/v1/auth/password/policy")) {
      await route.fulfill({
        status: 200,
        contentType: "application/json",
        body: JSON.stringify({
          minLength: 12,
          minCharacterTypes: 3,
          lowercase: true,
          uppercase: true,
          number: true,
          nonAlphanumeric: true,
        }),
      });
      return;
    }

    if (path.endsWith("/api/v1/auth/magic-link/verify")) {
      await route.fulfill({
        status: 200,
        contentType: "application/json",
        body: JSON.stringify({ status: "approved" }),
      });
      return;
    }

    if (path.endsWith("/api/v1/auth/login/code/verify")) {
      await route.fulfill({
        status: 200,
        contentType: "application/json",
        body: JSON.stringify({ status: "approved" }),
      });
      return;
    }

    if (path.endsWith("/api/v1/auth/login/code/verify-short")) {
      await route.fulfill({
        status: 200,
        contentType: "application/json",
        body: JSON.stringify({ status: "approved" }),
      });
      return;
    }

    if (path.endsWith("/api/v1/auth/consent") && method === "GET") {
      await route.fulfill({
        status: 200,
        contentType: "application/json",
        body: JSON.stringify({
          client: {
            client_name: "E2E Client",
            client_id: "e2e-client",
          },
          requested_scope: ["openid"],
          scope_details: {
            openid: {
              description: "OpenID",
              mandatory: true,
            },
          },
        }),
      });
      return;
    }

    if (path.endsWith("/api/v1/auth/qr/approve")) {
      await route.fulfill({
        status: 200,
        contentType: "application/json",
        body: JSON.stringify({ ok: true }),
      });
      return;
    }

    if (path.endsWith("/api/v1/client-log")) {
      await route.fulfill({
        status: 200,
        contentType: "application/json",
        body: JSON.stringify({ ok: true }),
      });
      return;
    }

    await route.fulfill({
      status: 200,
      contentType: "application/json",
      body: JSON.stringify({}),
    });
  });
}

async function expectRouteUrl(
  page: Page,
  expected: RegExp,
  testInfo: TestInfo,
): Promise<void> {
  await expect(page).toHaveURL(expected, {
    timeout: testInfo.project.name.includes("webkit") ? 15_000 : 5_000,
  });
}

test.describe("UserFront WASM route inventory (unauth)", () => {
  test.beforeEach(async ({ page }) => {
    await mockInventoryApis(page);
  });

  test("route: /", async ({ page }, testInfo) => {
    await page.goto("/");
    await expectRouteUrl(page, /\/(ko|en)\/signin(?:\?.*)?$/, testInfo);
  });

  test("route: /ko", async ({ page }, testInfo) => {
    await page.goto("/ko");
    await expectRouteUrl(page, /\/ko\/signin(?:\?.*)?$/, testInfo);
  });

  test("route: /ko/dashboard", async ({ page }, testInfo) => {
    await page.goto("/ko/dashboard");
    await expectRouteUrl(page, /\/ko\/signin$/, testInfo);
  });

  test("route: /ko/profile", async ({ page }, testInfo) => {
    await page.goto("/ko/profile");
    await expectRouteUrl(page, /\/ko\/signin$/, testInfo);
  });

  test("route: /ko/admin/users", async ({ page }, testInfo) => {
    await page.goto("/ko/admin/users");
    await expectRouteUrl(page, /\/ko\/signin$/, testInfo);
  });

  test("route: /ko/scan", async ({ page }, testInfo) => {
    await page.goto("/ko/scan");
    await expectRouteUrl(page, /\/ko\/signin$/, testInfo);
  });

  test("route: /ko/signin", async ({ page }, testInfo) => {
    await page.goto("/ko/signin");
    await expectRouteUrl(page, /\/ko\/signin$/, testInfo);
  });

  test("route: /ko/login", async ({ page }, testInfo) => {
    await page.goto("/ko/login");
    await expectRouteUrl(page, /\/ko\/login$/, testInfo);
  });

  test("route: /ko/signup", async ({ page }, testInfo) => {
    await page.goto("/ko/signup");
    await expectRouteUrl(page, /\/ko\/signup$/, testInfo);
  });

  test("route: /ko/registration", async ({ page }, testInfo) => {
    await page.goto("/ko/registration");
    await expectRouteUrl(page, /\/ko\/registration$/, testInfo);
  });

  test("route: /ko/verify", async ({ page }, testInfo) => {
    await page.goto("/ko/verify");
    await expectRouteUrl(page, /\/ko\/verify$/, testInfo);
  });

  test("route: /ko/verify/:token", async ({ page }, testInfo) => {
    await page.goto("/ko/verify/e2e-token");
    await expectRouteUrl(page, /\/ko\/verify\/e2e-token$/, testInfo);
  });

  test("route: /ko/verification", async ({ page }, testInfo) => {
    await page.goto("/ko/verification");
    await expectRouteUrl(page, /\/ko\/verification$/, testInfo);
  });

  test("route: /ko/verify-complete", async ({ page }, testInfo) => {
    await page.goto("/ko/verify-complete");
    await expectRouteUrl(page, /\/ko\/verify-complete$/, testInfo);
  });

  test("route: /ko/l/:shortCode", async ({ page }, testInfo) => {
    await page.goto("/ko/l/AB123456");
    await expectRouteUrl(page, /\/ko\/l\/AB123456$/, testInfo);
  });

  test("route: /ko/forgot-password", async ({ page }, testInfo) => {
    await page.goto("/ko/forgot-password");
    await expectRouteUrl(page, /\/ko\/forgot-password$/, testInfo);
  });

  test("route: /ko/recovery", async ({ page }, testInfo) => {
    await page.goto("/ko/recovery");
    await expectRouteUrl(page, /\/ko\/recovery$/, testInfo);
  });

  test("route: /ko/reset-password", async ({ page }, testInfo) => {
    await page.goto("/ko/reset-password?token=e2e-reset-token");
    await expectRouteUrl(
      page,
      /\/ko\/reset-password\?token=e2e-reset-token$/,
      testInfo,
    );
  });

  test("route: /ko/error", async ({ page }, testInfo) => {
    await page.goto("/ko/error?error=invalid_request");
    await expectRouteUrl(page, /\/ko\/error\?error=invalid_request$/, testInfo);
  });

  test("route: /ko/settings", async ({ page }, testInfo) => {
    await page.goto("/ko/settings");
    await expectRouteUrl(page, /\/ko\/settings$/, testInfo);
  });

  test("route: /ko/consent (missing challenge)", async ({ page }, testInfo) => {
    await page.goto("/ko/consent");
    await expectRouteUrl(page, /\/ko\/consent$/, testInfo);
  });

  test("route: /ko/consent?consent_challenge=...", async ({
    page,
  }, testInfo) => {
    await page.goto("/ko/consent?consent_challenge=e2e-consent");
    await expectRouteUrl(
      page,
      /\/ko\/consent\?consent_challenge=e2e-consent$/,
      testInfo,
    );
  });

  test("route: /ko/approve?ref=...", async ({ page }, testInfo) => {
    await page.goto("/ko/approve?ref=e2e-ref");
    await expectRouteUrl(
      page,
      /\/ko\/signin\?notice=qr_login_required$/,
      testInfo,
    );
  });

  test("route: /ko/ql/:ref", async ({ page }, testInfo) => {
    await page.goto("/ko/ql/e2e-ref");
    await expectRouteUrl(
      page,
      /\/ko\/signin\?notice=qr_login_required$/,
      testInfo,
    );
  });
});

test.describe("UserFront WASM route inventory (authed)", () => {
  test.beforeEach(async ({ page }) => {
    await seedTokenLogin(page);
    await mockInventoryApis(page);
  });

  test("route: /ko -> /ko/dashboard", async ({ page }, testInfo) => {
    await page.goto("/ko");
    await expectRouteUrl(page, /\/ko\/dashboard$/, testInfo);
  });

  test("route: /ko/dashboard", async ({ page }, testInfo) => {
    await page.goto("/ko/dashboard");
    await expectRouteUrl(page, /\/ko\/dashboard$/, testInfo);
  });

  test("route: /ko/profile", async ({ page }, testInfo) => {
    await page.goto("/ko/profile");
    await expectRouteUrl(page, /\/ko\/profile$/, testInfo);
  });

  test("route: /ko/admin/users", async ({ page }, testInfo) => {
    await page.goto("/ko/admin/users");
    await expectRouteUrl(page, /\/ko\/admin\/users$/, testInfo);
  });

  test("route: /ko/scan", async ({ page }, testInfo) => {
    await page.goto("/ko/scan");
    await expectRouteUrl(page, /\/ko\/scan$/, testInfo);
  });

  test("route: /ko/approve?ref=... -> /ko/dashboard", async ({
    page,
  }, testInfo) => {
    await page.goto("/ko/approve?ref=e2e-ref");
    await expectRouteUrl(page, /\/ko\/dashboard$/, testInfo);
  });

  test("route: /ko/ql/:ref -> /ko/dashboard", async ({ page }, testInfo) => {
    await page.goto("/ko/ql/e2e-ref");
    await expectRouteUrl(page, /\/ko\/dashboard$/, testInfo);
  });
});
