import { describe, it, expect, vi, beforeEach } from "vitest";
import { gameManagerRouter } from "./gameManager.ts";
import { getDb } from "../db.ts";

vi.mock("../db", () => ({
  getDb: vi.fn(),
}));

describe("gameManagerRouter", () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  it("should list games with pagination", async () => {
    const mockDb = {
      select: vi.fn().mockReturnThis(),
      from: vi.fn().mockReturnThis(),
      where: vi.fn().mockReturnThis(),
      orderBy: vi.fn().mockReturnThis(),
      limit: vi.fn().mockReturnThis(),
      offset: vi.fn().mockResolvedValue([
        {
          id: 1,
          gameName: "Test Game",
          provider: "Test Provider",
          category: "Slots",
          rtp: 96,
          volatility: "medium",
          isActive: 1,
        },
      ]),
    };

    const mockCountDb = {
      select: vi.fn().mockReturnThis(),
      from: vi.fn().mockReturnThis(),
      then: vi.fn().mockResolvedValue([{ count: 100 }]),
    };

    vi.mocked(getDb).mockReturnValueOnce(mockDb as any);
    vi.mocked(getDb).mockReturnValueOnce(mockCountDb as any);

    const caller = gameManagerRouter.createCaller({
      user: { id: 1, role: "admin" } as any,
      req: {} as any,
      res: {} as any,
    });

    const result = await caller.listGames({ page: 1, limit: 20 });

    expect(result.games).toHaveLength(1);
    expect(result.total).toBe(100);
    expect(result.page).toBe(1);
  });

  it("should get game analytics", async () => {
    const mockDb = {
      select: vi.fn().mockReturnThis(),
      from: vi.fn().mockReturnThis(),
      where: vi.fn().mockReturnThis(),
      then: vi.fn().mockResolvedValue([
        {
          id: 1,
          gameName: "Test Game",
          rtp: 96,
          volatility: "medium",
        },
      ]),
    };

    const mockAnalyticsDb = {
      select: vi.fn().mockReturnThis(),
      from: vi.fn().mockReturnThis(),
      where: vi.fn().mockResolvedValue([
        {
          totalSpins: 1000,
          totalWagered: 10000,
          totalWon: 9600,
          uniquePlayers: 50,
          avgBetSize: 10,
        },
      ]),
    };

    vi.mocked(getDb).mockReturnValueOnce(mockDb as any);
    vi.mocked(getDb).mockReturnValueOnce(mockAnalyticsDb as any);

    const caller = gameManagerRouter.createCaller({
      user: { id: 1, role: "admin" } as any,
      req: {} as any,
      res: {} as any,
    });

    const result = await caller.getGameAnalytics({ gameId: 1, days: 7 });

    expect(result.game.gameName).toBe("Test Game");
    expect(result.analytics.totalSpins).toBe(1000);
    expect(result.analytics.rtp).toBe(96);
  });

  it("should toggle game status", async () => {
    const mockDb = {
      select: vi.fn().mockReturnThis(),
      from: vi.fn().mockReturnThis(),
      where: vi.fn().mockReturnThis(),
      then: vi.fn().mockResolvedValue([
        {
          id: 1,
          gameName: "Test Game",
          isActive: 1,
        },
      ]),
      update: vi.fn().mockReturnThis(),
      set: vi.fn().mockReturnThis(),
    };

    const mockInsertDb = {
      insert: vi.fn().mockReturnThis(),
      values: vi.fn().mockResolvedValue({}),
    };

    vi.mocked(getDb).mockReturnValueOnce(mockDb as any);
    vi.mocked(getDb).mockReturnValueOnce(mockInsertDb as any);

    const caller = gameManagerRouter.createCaller({
      user: { id: 1, role: "admin" } as any,
      req: {} as any,
      res: {} as any,
    });

    const result = await caller.toggleGameStatus({ gameId: 1, isActive: false });

    expect(result.success).toBe(true);
    expect(result.isActive).toBe(false);
  });

  it("should require admin role for game management", async () => {
    const caller = gameManagerRouter.createCaller({
      user: { id: 1, role: "user" } as any,
      req: {} as any,
      res: {} as any,
    });

    try {
      await caller.listGames({ page: 1, limit: 20 });
      expect.fail("Should throw FORBIDDEN error");
    } catch (error: any) {
      expect(error.code).toBe("FORBIDDEN");
    }
  });
});
