import { describe, it, expect, vi, beforeEach } from "vitest";
import { renderHook, waitFor } from "@testing-library/react";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import type { ReactNode } from "react";

import {
  useGamesList,
  useGameDetail,
  useGameConfigSchema,
  useGameDefaults,
} from "@/hooks/useGames";

vi.mock("@/lib/api", () => ({
  apiClient: {
    get: vi.fn(),
  },
}));

import { apiClient } from "@/lib/api";

function createWrapper() {
  const queryClient = new QueryClient({
    defaultOptions: { queries: { retry: false } },
  });
  return function Wrapper({ children }: { children: ReactNode }) {
    return (
      <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
    );
  };
}

describe("useGamesList", () => {
  beforeEach(() => {
    vi.mocked(apiClient.get).mockReset();
  });

  it("should fetch games list", async () => {
    const mockGames = [
      { game_type: "arma3", display_name: "Arma 3", version: "1.0", capabilities: ["rcon", "mods"] },
    ];
    vi.mocked(apiClient.get).mockResolvedValueOnce({
      data: { success: true, data: mockGames },
    });

    const { result } = renderHook(() => useGamesList(), {
      wrapper: createWrapper(),
    });

    await waitFor(() => expect(result.current.isSuccess).toBe(true));
    expect(result.current.data).toEqual(mockGames);
    expect(apiClient.get).toHaveBeenCalledWith("/api/games");
  });
});

describe("useGameDetail", () => {
  beforeEach(() => {
    vi.mocked(apiClient.get).mockReset();
  });

  it("should fetch game detail", async () => {
    const mockDetail = {
      game_type: "arma3",
      display_name: "Arma 3",
      version: "1.0",
      schema_version: 1,
      config_sections: ["server", "basic", "profile", "launch", "rcon"],
      capabilities: ["rcon", "mods", "missions"],
      allowed_executables: ["arma3server_x64.exe"],
    };
    vi.mocked(apiClient.get).mockResolvedValueOnce({
      data: { success: true, data: mockDetail },
    });

    const { result } = renderHook(() => useGameDetail("arma3"), {
      wrapper: createWrapper(),
    });

    await waitFor(() => expect(result.current.isSuccess).toBe(true));
    expect(result.current.data).toEqual(mockDetail);
    expect(apiClient.get).toHaveBeenCalledWith("/api/games/arma3");
  });

  it("should not fetch when gameType is empty", () => {
    renderHook(() => useGameDetail(""), { wrapper: createWrapper() });
    expect(apiClient.get).not.toHaveBeenCalled();
  });
});

describe("useGameConfigSchema", () => {
  beforeEach(() => {
    vi.mocked(apiClient.get).mockReset();
  });

  it("should fetch config schema", async () => {
    const mockSchema = { server: { type: "object", properties: {} } };
    vi.mocked(apiClient.get).mockResolvedValueOnce({
      data: { success: true, data: mockSchema },
    });

    const { result } = renderHook(() => useGameConfigSchema("arma3"), {
      wrapper: createWrapper(),
    });

    await waitFor(() => expect(result.current.isSuccess).toBe(true));
    expect(result.current.data).toEqual(mockSchema);
    expect(apiClient.get).toHaveBeenCalledWith("/api/games/arma3/config-schema");
  });
});

describe("useGameDefaults", () => {
  beforeEach(() => {
    vi.mocked(apiClient.get).mockReset();
  });

  it("should fetch game defaults", async () => {
    const mockDefaults = {
      server: { hostname: "Arma 3 Server", max_players: 64 },
      basic: { min_bandwidth: 131072 },
    };
    vi.mocked(apiClient.get).mockResolvedValueOnce({
      data: { success: true, data: mockDefaults },
    });

    const { result } = renderHook(() => useGameDefaults("arma3"), {
      wrapper: createWrapper(),
    });

    await waitFor(() => expect(result.current.isSuccess).toBe(true));
    expect(result.current.data).toEqual(mockDefaults);
    expect(apiClient.get).toHaveBeenCalledWith("/api/games/arma3/defaults");
  });

  it("should not fetch when gameType is empty", () => {
    renderHook(() => useGameDefaults(""), { wrapper: createWrapper() });
    expect(apiClient.get).not.toHaveBeenCalled();
  });
});