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

const appNamePlaceholder = /My Awesome Application|예: 멋진 애플리케이션/i;

test.describe("DevFront role report", () => {
  test.beforeEach(async ({ page }) => {
    page.on("dialog", async (dialog) => {
      await dialog.accept();
    });
  });

  test("user can enter and sees empty RP list", async ({ page }, testInfo) => {
    await seedAuth(page, "user");
    await installDevApiMock(page, {
      clients: [],
      consents: [] as Consent[],
      auditLogs: [] as AuditLog[],
    });

    await page.goto("/clients");
    await expect(
      page.getByText(/조회 가능한 RP가 없습니다|No RPs are available/i),
    ).toBeVisible();
    await expect(
      page.getByRole("heading", {
        name: /^연동 앱$|^Connected Application$/i,
      }),
    ).toBeVisible();
    await captureEvidence(page, testInfo, "role-user-empty-rps");
  });

  test("user sees developer request entry point on overview", async ({
    page,
  }, testInfo) => {
    await seedAuth(page, "user");
    await installDevApiMock(page, {
      clients: [],
      consents: [] as Consent[],
      auditLogs: [] as AuditLog[],
      auditLogsByCursor: undefined,
      developerRequests: [],
    });

    await page.goto("/");
    await expect(
      page.getByText(
        /대시보드는 개발자 권한이 있어야 볼 수 있습니다|개발자 권한 신청을 검토 중입니다./,
      ),
    ).toBeVisible();
    const requestBtn = page.getByRole("button", {
      name: /개발자 권한 신청/,
    });
    await expect(requestBtn).toBeVisible();
    await requestBtn.click();
    await expect(page).toHaveURL(/\/developer-requests$/);
    await captureEvidence(page, testInfo, "role-user-overview-request-entry");
  });

  test("user with approved developer request sees overview without CTA", async ({
    page,
  }, testInfo) => {
    await seedAuth(page, "user");
    await installDevApiMock(page, {
      clients: [],
      consents: [] as Consent[],
      auditLogs: [] as AuditLog[],
      auditLogsByCursor: undefined,
      developerRequests: [
        {
          id: "req-approved",
          userId: "playwright-user",
          userName: "Playwright User",
          name: "Playwright User",
          userEmail: "playwright@example.com",
          organization: "Tenant A",
          reason: "Need access",
          status: "approved",
          createdAt: "2026-05-29T00:00:00.000Z",
          updatedAt: "2026-05-29T00:00:00.000Z",
          approvedAt: "2026-05-29T00:10:00.000Z",
        },
      ],
    });

    await page.goto("/");
    await expect(
      page.getByRole("heading", { name: /운영 현황/ }),
    ).toBeVisible();
    await expect(
      page.getByRole("button", { name: /개발자 권한 신청/ }),
    ).toHaveCount(0);
    await captureEvidence(page, testInfo, "role-user-overview-approved");
  });

  test("rp_admin sees only assigned Gitea app and its logs", async ({
    page,
  }, testInfo) => {
    await seedAuth(page, "rp_admin");
    const state = {
      clients: [makeClient("gitea-client", { name: "Gitea" })],
      consents: [] as Consent[],
      auditLogs: [
        {
          event_id: "evt-rp-1",
          timestamp: "2026-03-04T01:00:00.000Z",
          user_id: "rp-admin-user",
          event_type: "CLIENT_UPDATE",
          status: "success" as const,
          ip_address: "127.0.0.1",
          user_agent: "playwright",
          details: JSON.stringify({
            action: "UPDATE_CLIENT",
            target_id: "gitea-client",
            tenant_id: "tenant-a",
          }),
        },
      ] as AuditLog[],
    };
    await installDevApiMock(page, state);

    await page.goto("/clients");
    await expect(
      page.getByRole("link", { name: "Gitea", exact: true }),
    ).toBeVisible();
    await expect(
      page.getByRole("cell", { name: "gitea-client" }),
    ).toBeVisible();
    await captureEvidence(page, testInfo, "role-rp-admin-clients");

    await page.goto("/audit-logs");
    await expect(page.getByText("UPDATE_CLIENT")).toBeVisible();
    await expect(page.getByText("gitea-client")).toBeVisible();
    await captureEvidence(page, testInfo, "role-rp-admin-audit");
  });

  test("tenant_admin can manage tenant apps and see tenant logs", async ({
    page,
  }, testInfo) => {
    await seedAuth(page, "tenant_admin");
    const state = {
      clients: [
        makeClient("tenant-a-app-1", { name: "Tenant A CRM" }),
        makeClient("tenant-a-app-2", { name: "Tenant A ERP" }),
      ],
      consents: [] as Consent[],
      auditLogs: [] as AuditLog[],
      auditLogsByCursor: undefined,
    };
    await installDevApiMock(page, state);

    await page.goto("/clients");
    await expect(page.getByText("Tenant A CRM")).toBeVisible();
    await expect(page.getByText("Tenant A ERP")).toBeVisible();
    await captureEvidence(page, testInfo, "role-tenant-admin-clients");

    await page.goto("/clients/tenant-a-app-1/settings");
    await page
      .getByPlaceholder(appNamePlaceholder)
      .fill("Tenant A CRM Updated");

    const updatePromise = page.waitForResponse(
      (r) =>
        r.url().includes("/api/v1/dev/clients") &&
        r.request().method() === "PUT",
    );
    await page.getByRole("button", { name: /^저장$|^Save$/i }).click();
    await updatePromise;

    await page.goto("/audit-logs");
    await expect(page.getByText("UPDATE_CLIENT")).toBeVisible({
      timeout: 30000,
    });
    await expect(page.getByText("tenant-a-app-1")).toBeVisible();
    await captureEvidence(page, testInfo, "role-tenant-admin-audit");
  });

  test("super_admin sees all and can generate log entries", async ({
    page,
  }, testInfo) => {
    await seedAuth(page, "super_admin");
    const state = {
      clients: [
        makeClient("tenant-a-app", { name: "Tenant A App" }),
        makeClient("tenant-b-app", { name: "Tenant B App" }),
      ],
      consents: [] as Consent[],
      auditLogs: [] as AuditLog[],
      auditLogsByCursor: undefined,
    };
    await installDevApiMock(page, state);

    await page.goto("/clients");
    await expect(page.getByText("Tenant A App")).toBeVisible();
    await expect(page.getByText("Tenant B App")).toBeVisible();
    await captureEvidence(page, testInfo, "role-super-admin-clients");

    await page.goto("/clients/new");
    await page
      .getByPlaceholder(appNamePlaceholder)
      .fill("Super Admin Created App");
    await page
      .getByPlaceholder(/https:\/\/app\.example\.com\/callback/i)
      .fill("https://super-admin.example.com/callback");

    const createPromise = page.waitForResponse(
      (r) =>
        r.url().includes("/api/v1/dev/clients") &&
        r.request().method() === "POST",
    );
    await page.getByRole("button", { name: /앱 생성|Create/i }).click();
    await createPromise;
    await expect(page).toHaveURL(/\/clients\/client-\d+\/settings$/);
    await expect
      .poll(() =>
        state.auditLogs.some((item) => {
          try {
            return JSON.parse(item.details)?.action === "CREATE_CLIENT";
          } catch {
            return false;
          }
        }),
      )
      .toBe(true);

    await page.goto("/audit-logs");
    await expect(page.getByText("CREATE_CLIENT")).toBeVisible({
      timeout: 30000,
    });
    await captureEvidence(page, testInfo, "role-super-admin-audit");
  });
});
