import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { fireEvent, render, screen, waitFor } from "@testing-library/react";
import { beforeEach, describe, expect, it, vi } from "vitest";
import {
  fetchOrySSOTSystemStatus,
  flushIdentityCache,
} from "../../lib/adminApi";
import { createI18nMock } from "../../test/i18nMock";
import UserProjectionPage from "./UserProjectionPage";

vi.mock("../../lib/i18n", () => createI18nMock());

let currentRole = "super_admin";

vi.mock("../../lib/adminApi", () => ({
  fetchMe: vi.fn(async () => ({ role: currentRole })),
  fetchOrySSOTSystemStatus: vi.fn(async () => ({
    userProjection: {
      name: "kratos_users",
      status: "ready",
      ready: true,
      lastSyncedAt: "2026-05-11T03:00:00Z",
      updatedAt: "2026-05-11T03:00:10Z",
      projectedUsers: 152,
    },
    identityCache: {
      status: "ready",
      redisReady: true,
      observedCount: 151,
      lastRefreshedAt: "2026-05-11T03:00:00Z",
      updatedAt: "2026-05-11T03:00:10Z",
      keyCount: 153,
    },
  })),
  flushIdentityCache: vi.fn(async () => ({
    status: "success",
    flushedKeys: 153,
    updatedAt: "2026-05-11T03:02:00Z",
  })),
}));

function renderPage() {
  const queryClient = new QueryClient({
    defaultOptions: {
      queries: { retry: false },
      mutations: { retry: false },
    },
  });

  return render(
    <QueryClientProvider client={queryClient}>
      <UserProjectionPage />
    </QueryClientProvider>,
  );
}

describe("UserProjectionPage", () => {
  beforeEach(() => {
    currentRole = "super_admin";
    vi.clearAllMocks();
    vi.spyOn(window, "confirm").mockReturnValue(true);
    window.localStorage.setItem("locale", "ko");
  });

  it("renders Ory SSOT and Redis identity cache status for super_admin", async () => {
    renderPage();

    expect(await screen.findByText("Ory SSOT 시스템")).toBeInTheDocument();
    expect(
      await screen.findByText(
        "Kratos 원장과 Redis identity cache 상태를 분리해서 확인합니다.",
      ),
    ).toBeInTheDocument();
    expect(await screen.findByText("Redis identity cache")).toBeInTheDocument();
    expect(screen.getAllByText("준비됨").length).toBeGreaterThan(0);
    expect(screen.getByText("관측 identity")).toBeInTheDocument();
    expect(screen.getByText("152")).toBeInTheDocument();
    expect(screen.getByText("151")).toBeInTheDocument();
    expect(fetchOrySSOTSystemStatus).toHaveBeenCalled();
  });

  it("flushes only the Redis identity cache for super_admin", async () => {
    renderPage();

    await screen.findByText("Ory SSOT 시스템");
    expect(screen.queryByRole("button", { name: /재동기화/ })).toBeNull();
    expect(
      screen.queryByRole("button", { name: /초기화 후 재구축/ }),
    ).toBeNull();
    fireEvent.click(screen.getByRole("button", { name: /Redis cache flush/ }));

    await waitFor(() => {
      expect(flushIdentityCache).toHaveBeenCalledTimes(1);
    });
  });

  it("blocks non-super admins", async () => {
    currentRole = "tenant_admin";

    renderPage();

    expect(await screen.findByText("접근 권한이 없습니다")).toBeInTheDocument();
    expect(screen.queryByText("Ory SSOT 시스템")).not.toBeInTheDocument();
    expect(fetchOrySSOTSystemStatus).not.toHaveBeenCalled();
  });

  it("renders localized labels in English", async () => {
    window.localStorage.setItem("locale", "en");
    renderPage();

    expect(await screen.findByText("Ory SSOT System")).toBeInTheDocument();
    expect(
      await screen.findByText(
        "Review Kratos source-of-truth and Redis identity cache status separately.",
      ),
    ).toBeInTheDocument();
    expect(screen.getByText("Redis cache flush")).toBeInTheDocument();
    expect((await screen.findAllByText("ready")).length).toBeGreaterThan(0);
  });
});
