import { expect, test } from "@playwright/test";
import {
  getPersistedOidcUser,
  installDevApiMock,
  seedAuth,
} from "./helpers/devfront-fixtures";
import { captureEvidence } from "./helpers/evidence";

test.describe("DevFront refresh token renewal", () => {
  test.afterEach(async ({ page }, testInfo) => {
    if (testInfo.status === "passed") {
      await captureEvidence(page, testInfo, testInfo.title);
    }
  });

  test.beforeEach(async ({ page }) => {
    await seedAuth(page, {
      expiresInSeconds: 60,
      refreshToken: "playwright-refresh-token",
      state: { returnTo: "/clients" },
    });

    await installDevApiMock(page, {
      clients: [],
      consents: [],
      auditLogs: [],
      users: [],
      tenants: [],
    });
  });

  test("exchanges the refresh token for a new access token on silent renewal", async ({
    page,
  }) => {
    let tokenRequestBody = "";
    let authorizeRequested = false;

    await page.route("**/oidc/token", async (route) => {
      const request = route.request();
      tokenRequestBody = request.postData() ?? "";

      await route.fulfill({
        status: 200,
        contentType: "application/json",
        headers: { "Access-Control-Allow-Origin": "*" },
        body: JSON.stringify({
          access_token: "rotated-access-token",
          expires_in: 3600,
          refresh_token: "rotated-refresh-token",
          scope: "openid offline_access profile email",
          session_state: "rotated-session-state",
          token_type: "Bearer",
        }),
      });
    });

    await page.route("**/oidc/auth**", async (route) => {
      authorizeRequested = true;
      await route.fulfill({
        status: 500,
        body: "unexpected authorize request",
      });
    });

    await page.goto("/clients");

    await expect(page.getByRole("link", { name: "Clients" })).toBeVisible();

    const tokenRequestPromise = page.waitForRequest(
      (request) =>
        request.url().endsWith("/oidc/token") && request.method() === "POST",
    );

    await page.getByRole("button", { name: "Open account menu" }).click();
    await page.getByRole("menuitem", { name: "My Profile" }).click();

    const tokenRequest = await tokenRequestPromise;
    const tokenParams = new URLSearchParams(tokenRequestBody);

    expect(tokenParams.get("grant_type")).toBe("refresh_token");
    expect(tokenParams.get("refresh_token")).toBe("playwright-refresh-token");

    await expect(page.getByRole("heading", { name: "내 정보" })).toBeVisible();
    await expect
      .poll(async () => {
        const storedUser = await getPersistedOidcUser(page);
        return storedUser?.access_token;
      })
      .toBe("rotated-access-token");
    await expect
      .poll(async () => {
        const storedUser = await getPersistedOidcUser(page);
        return storedUser?.refresh_token;
      })
      .toBe("rotated-refresh-token");
    expect(tokenRequest.url()).toContain("/oidc/token");
    expect(authorizeRequested).toBe(false);
  });
});
