import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { render, screen, waitFor } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { MemoryRouter } from "react-router-dom";
import { beforeEach, describe, expect, it, vi } from "vitest";
import {
  fetchApiKeys,
  rotateApiKeySecret,
  updateApiKeyScopes,
} from "../../lib/adminApi";
import ApiKeyListPage from "./ApiKeyListPage";

vi.mock("../../lib/i18n", () => ({
  t: (_key: string, fallback?: string) => fallback ?? "",
}));

vi.mock("../../lib/adminApi", () => ({
  fetchApiKeys: vi.fn(async () => ({
    items: [
      {
        id: "api-key-id",
        name: "org-context-client",
        client_id: "client-id-stable",
        scopes: ["audit:read"],
        status: "active",
        createdAt: "2026-05-13T00:00:00Z",
      },
    ],
    total: 1,
  })),
  deleteApiKey: vi.fn(async () => undefined),
  updateApiKeyScopes: vi.fn(async () => ({
    id: "api-key-id",
    name: "org-context-client",
    client_id: "client-id-stable",
    scopes: ["audit:read", "org-context:read"],
    status: "active",
    createdAt: "2026-05-13T00:00:00Z",
  })),
  rotateApiKeySecret: vi.fn(async () => ({
    apiKey: {
      id: "api-key-id",
      name: "org-context-client",
      client_id: "client-id-stable",
      scopes: ["audit:read"],
      status: "active",
      createdAt: "2026-05-13T00:00:00Z",
    },
    clientSecret: "rotated-secret",
  })),
}));

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

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

describe("ApiKeyListPage", () => {
  beforeEach(() => {
    vi.clearAllMocks();
    vi.spyOn(window, "confirm").mockReturnValue(true);
  });

  it("updates scopes without changing client_id", async () => {
    const user = userEvent.setup({ delay: null });
    renderPage();

    expect(await screen.findByText("client-id-stable")).toBeInTheDocument();

    await user.click(screen.getByRole("button", { name: /권한 수정/ }));
    await user.click(screen.getByRole("button", { name: /조직 Context 조회/ }));
    await user.click(screen.getByRole("button", { name: /권한 저장/ }));

    await waitFor(() => {
      expect(updateApiKeyScopes).toHaveBeenCalledWith("api-key-id", {
        scopes: expect.arrayContaining(["audit:read", "org-context:read"]),
      });
    });
  }, 15_000);

  it("rotates only the secret and shows the one-time secret", async () => {
    const user = userEvent.setup();
    renderPage();

    expect(await screen.findByText("client-id-stable")).toBeInTheDocument();

    await user.click(screen.getByRole("button", { name: /Secret 재발급/ }));

    await waitFor(() => {
      expect(rotateApiKeySecret).toHaveBeenCalledWith("api-key-id");
    });
    expect(
      await screen.findByDisplayValue("rotated-secret"),
    ).toBeInTheDocument();
    expect(fetchApiKeys).toHaveBeenCalled();
  });

  it("refresh button refetches the list without navigation", async () => {
    const user = userEvent.setup();
    renderPage();

    await screen.findByText("client-id-stable");

    const refreshButton = screen.getByRole("button", { name: /새로고침/ });
    expect(refreshButton).toHaveAttribute("type", "button");

    await user.click(refreshButton);

    await waitFor(() => {
      expect(fetchApiKeys).toHaveBeenCalledTimes(2);
    });
  });
});
