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 {
  fetchUserProjectionStatus,
  reconcileUserProjection,
  resetUserProjection,
} 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 })),
  fetchUserProjectionStatus: vi.fn(async () => ({
    name: "kratos_users",
    status: "ready",
    ready: true,
    lastSyncedAt: "2026-05-11T03:00:00Z",
    updatedAt: "2026-05-11T03:00:10Z",
    projectedUsers: 152,
  })),
  reconcileUserProjection: vi.fn(async () => ({
    status: "success",
    syncedUsers: 152,
    updatedAt: "2026-05-11T03:01:00Z",
  })),
  resetUserProjection: vi.fn(async () => ({
    status: "success",
    syncedUsers: 152,
    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 projection status for super_admin", async () => {
    renderPage();

    expect(
      await screen.findByText("사용자 동기화 관리"),
    ).toBeInTheDocument();
    expect(
      await screen.findByText(
        "Kratos 사용자 read model을 확인하고 동기화 상태를 갱신합니다.",
      ),
    ).toBeInTheDocument();
    expect(
      await screen.findByText("Kratos 사용자 동기화"),
    ).toBeInTheDocument();
    expect(screen.getByText("준비됨")).toBeInTheDocument();
    expect(screen.getByText("152")).toBeInTheDocument();
    expect(fetchUserProjectionStatus).toHaveBeenCalled();
  });

  it("runs reconcile and reset actions for super_admin", async () => {
    renderPage();

    await screen.findByText("사용자 동기화 관리");
    fireEvent.click(screen.getByRole("button", { name: /재동기화/ }));

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

    fireEvent.click(screen.getByRole("button", { name: /초기화 후 재구축/ }));

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

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

    renderPage();

    expect(await screen.findByText("접근 권한이 없습니다")).toBeInTheDocument();
    expect(
      screen.queryByText("사용자 동기화 관리"),
    ).not.toBeInTheDocument();
    expect(fetchUserProjectionStatus).not.toHaveBeenCalled();
  });

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

    expect(
      await screen.findByText("User Projection Management"),
    ).toBeInTheDocument();
    expect(
      await screen.findByText("Review and sync the Kratos user read model."),
    ).toBeInTheDocument();
    expect(screen.getByText("Re-sync")).toBeInTheDocument();
    expect(await screen.findByText("ready")).toBeInTheDocument();
  });
});
