import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { act } from "react";
import { createRoot, type Root } from "react-dom/client";
import { MemoryRouter, Route, Routes } from "react-router-dom";
import { afterEach, describe, expect, it, vi } from "vitest";
import { ForbiddenMessage } from "../../components/common/ForbiddenMessage";
import AuditLogsPage from "../audit/AuditLogsPage";
import AuthPage from "../auth/AuthPage";
import ClientConsentsPage from "../clients/ClientConsentsPage";
import ClientDetailsPage from "../clients/ClientDetailsPage";
import ClientGeneralPage from "../clients/ClientGeneralPage";
import ClientsPage from "../clients/ClientsPage";
import { ClientFederationPage } from "../clients/routes/ClientFederationPage";
import DashboardPage from "../dashboard/DashboardPage";
import ProfilePage from "../profile/ProfilePage";

globalThis.IS_REACT_ACT_ENVIRONMENT = true;

vi.mock("react-oidc-context", () => ({
  useAuth: () => ({
    isAuthenticated: true,
    isLoading: false,
    user: {
      access_token: "access-token",
      profile: {
        sub: "user-1",
        role: "super_admin",
        tenant_id: "tenant-1",
      },
    },
    signinRedirect: vi.fn(),
    removeUser: vi.fn(),
  }),
}));

vi.mock("../../lib/i18n", () => ({
  t: (key: string, fallback?: string, vars?: Record<string, unknown>) => {
    let text = fallback ?? key;
    for (const [name, value] of Object.entries(vars ?? {})) {
      text = text.replaceAll(`{{${name}}}`, String(value));
    }
    return text;
  },
}));

const clientSummary = {
  id: "client-a",
  name: "Console App",
  type: "private" as const,
  status: "active" as const,
  createdAt: "2026-05-01T00:00:00Z",
  redirectUris: ["https://app.example/callback"],
  scopes: ["openid", "profile"],
  tokenEndpointAuthMethod: "client_secret_basic",
  metadata: {
    headless_login_enabled: true,
    headless_login_jwks_uri: "https://app.example/jwks.json",
  },
};

const clientDetail = {
  client: {
    ...clientSummary,
    clientSecret: "secret-value",
    jwksUri: "https://app.example/jwks.json",
    grantTypes: ["authorization_code"],
    responseTypes: ["code"],
  },
  endpoints: {
    discovery: "https://sso.example/.well-known/openid-configuration",
    issuer: "https://sso.example",
    authorization: "https://sso.example/oauth2/auth",
    token: "https://sso.example/oauth2/token",
    userinfo: "https://sso.example/userinfo",
  },
  headlessJwksCache: {
    clientId: "client-a",
    jwksUri: "https://app.example/jwks.json",
    cachedAt: "2026-05-01T00:00:00Z",
    expiresAt: "2026-05-02T00:00:00Z",
    lastRefreshStatus: "success" as const,
    cachedKids: ["kid-1"],
    parsedKeys: [{ kid: "kid-1", kty: "RSA", use: "sig", alg: "RS256" }],
  },
};

vi.mock("../../lib/devApi", () => ({
  fetchClients: vi.fn(async () => ({
    items: [clientSummary],
    limit: 100,
    offset: 0,
  })),
  fetchDevStats: vi.fn(async () => ({
    total_clients: 1,
    active_sessions: 12,
    auth_failures_24h: 2,
  })),
  fetchClient: vi.fn(async () => clientDetail),
  updateClientStatus: vi.fn(async () => clientDetail),
  createClient: vi.fn(async () => clientDetail),
  updateClient: vi.fn(async () => clientDetail),
  rotateClientSecret: vi.fn(async () => clientDetail),
  refreshHeadlessJwksCache: vi.fn(async () => clientDetail),
  revokeHeadlessJwksCache: vi.fn(async () => undefined),
  deleteClient: vi.fn(async () => undefined),
  fetchConsents: vi.fn(async () => ({
    items: [
      {
        subject: "user-1",
        userName: "Consent User",
        clientId: "client-a",
        clientName: "Console App",
        grantedScopes: ["openid", "profile"],
        authenticatedAt: "2026-05-01T02:00:00Z",
        createdAt: "2026-05-01T00:00:00Z",
        status: "active",
        tenantId: "tenant-1",
        tenantName: "Hanmac",
      },
    ],
  })),
  revokeConsent: vi.fn(async () => undefined),
  listIdpConfigsForClient: vi.fn(async () => [
    {
      id: "idp-1",
      client_id: "client-a",
      provider_type: "oidc",
      display_name: "Workspace OIDC",
      status: "active",
      issuer_url: "https://accounts.example",
      oidc_client_id: "oidc-client",
      scopes: "openid email profile",
      createdAt: "2026-05-01T00:00:00Z",
      updatedAt: "2026-05-01T00:00:00Z",
    },
  ]),
  createIdpConfigForClient: vi.fn(async (payload) => ({
    id: "idp-1",
    ...payload,
    status: "active",
    createdAt: "2026-05-01T00:00:00Z",
    updatedAt: "2026-05-01T00:00:00Z",
  })),
  updateIdpConfig: vi.fn(async (_clientId, idpId, payload) => ({
    id: idpId,
    client_id: "client-a",
    provider_type: "oidc",
    display_name: "Provider",
    status: "active",
    createdAt: "2026-05-01T00:00:00Z",
    updatedAt: "2026-05-01T00:00:00Z",
    ...payload,
  })),
  deleteIdpConfig: vi.fn(async () => undefined),
  fetchDevAuditLogs: vi.fn(async () => ({
    items: [
      {
        event_id: "event-1",
        timestamp: "2026-05-01T00:00:00Z",
        user_id: "user-1",
        event_type: "client.update",
        status: "success",
        ip_address: "127.0.0.1",
        user_agent: "vitest",
        details: JSON.stringify({
          action: "client.update",
          target_id: "client-a",
          tenant_id: "tenant-1",
          request_id: "req-1",
        }),
      },
    ],
    limit: 50,
  })),
  fetchMyTenants: vi.fn(async () => [
    { id: "tenant-1", name: "Hanmac", slug: "hanmac" },
  ]),
}));

vi.mock("../auth/authApi", () => ({
  fetchMe: vi.fn(async () => ({
    id: "user-1",
    name: "Org User",
    email: "org@example.com",
    phone: "010-0000-0000",
    role: "super_admin",
    department: "Platform",
    tenantId: "tenant-1",
    tenant: { id: "tenant-1", name: "Hanmac", slug: "hanmac" },
  })),
}));

const roots: Root[] = [];

afterEach(() => {
  for (const root of roots.splice(0)) {
    act(() => {
      root.unmount();
    });
  }
});

async function renderWithProviders(
  element: React.ReactElement,
  initialEntry = "/",
) {
  const container = document.createElement("div");
  document.body.appendChild(container);
  const root = createRoot(container);
  roots.push(root);
  const queryClient = new QueryClient({
    defaultOptions: {
      queries: { retry: false },
      mutations: { retry: false },
    },
  });

  await act(async () => {
    root.render(
      <QueryClientProvider client={queryClient}>
        <MemoryRouter initialEntries={[initialEntry]}>{element}</MemoryRouter>
      </QueryClientProvider>,
    );
  });

  await act(async () => {
    await new Promise((resolve) => setTimeout(resolve, 0));
  });

  return container;
}

describe("orgfront page smoke coverage", () => {
  it("renders the dashboard content", async () => {
    const container = await renderWithProviders(<DashboardPage />);

    expect(container.textContent).toContain("RP 등록 현황");
    expect(container.textContent).toContain("Stack readiness");
  });

  it("renders static auth guidance and forbidden messages", async () => {
    const auth = await renderWithProviders(<AuthPage />);
    expect(auth.textContent).toContain("Admin auth guardrails");
    expect(auth.textContent).toContain("TTL discipline");

    const forbidden = await renderWithProviders(
      <ForbiddenMessage resourceToken="clients" />,
    );
    expect(forbidden.textContent).toContain("연동 앱 접근 권한 없음");
  });

  it("renders client list, detail, edit, consent, and federation pages", async () => {
    const clients = await renderWithProviders(
      <Routes>
        <Route path="/clients" element={<ClientsPage />} />
      </Routes>,
      "/clients",
    );
    expect(clients.textContent).toContain("Console App");

    const details = await renderWithProviders(
      <Routes>
        <Route path="/clients/:id" element={<ClientDetailsPage />} />
      </Routes>,
      "/clients/client-a",
    );
    expect(details.textContent).toContain("Client Secret");
    expect(details.textContent).toContain("https://sso.example/oauth2/token");

    const general = await renderWithProviders(
      <Routes>
        <Route path="/clients/:id/edit" element={<ClientGeneralPage />} />
      </Routes>,
      "/clients/client-a/edit",
    );
    expect(general.textContent).toContain("Console App");

    const consents = await renderWithProviders(
      <Routes>
        <Route path="/clients/:id/consents" element={<ClientConsentsPage />} />
      </Routes>,
      "/clients/client-a/consents",
    );
    expect(consents.textContent).toContain("Consent User");

    const federation = await renderWithProviders(
      <Routes>
        <Route
          path="/clients/:id/federation"
          element={<ClientFederationPage />}
        />
      </Routes>,
      "/clients/client-a/federation",
    );
    expect(federation.textContent).toContain("Workspace OIDC");
  });

  it("renders audit logs and profile pages", async () => {
    const auditLogs = await renderWithProviders(<AuditLogsPage />);
    expect(auditLogs.textContent).toContain("client.update");
    expect(auditLogs.textContent).toContain("Loaded 1 rows");

    const profile = await renderWithProviders(<ProfilePage />);
    expect(profile.textContent).toContain("Org User");
    expect(profile.textContent).toContain("Hanmac");
  });
});
