import { describe, it, expect, vi, beforeEach } from "vitest";

const mockFindMany = vi.fn();

const mockDb = {
  query: {
    scoringEvents: { findMany: mockFindMany },
  },
};

vi.mock("~/database/context", () => ({
  database: () => mockDb,
}));

vi.mock("~/database/schema", () => ({
  scoringEvents: {
    sportsSeasonId: "se.sports_season_id",
    tournamentId: "se.tournament_id",
  },
}));

vi.mock("drizzle-orm", () => ({
  eq: (col: unknown, val: unknown) => ({ type: "eq", col, val }),
  and: (...args: unknown[]) => ({ type: "and", args }),
  isNotNull: (col: unknown) => ({ type: "isNotNull", col }),
}));

import {
  getTournamentsBySportsSeason,
  getSportsSeasonsByTournament,
} from "../scoring-event";

const SEASON_ID = "ss-1";
const TOURNAMENT_ID_A = "t-a";
const TOURNAMENT_ID_B = "t-b";

const mockTournamentA = { id: TOURNAMENT_ID_A, name: "Wimbledon", year: 2026 };
const mockTournamentB = { id: TOURNAMENT_ID_B, name: "US Open", year: 2026 };

beforeEach(() => {
  vi.clearAllMocks();
});

describe("getTournamentsBySportsSeason", () => {
  it("returns one row per unique tournament, deduplicating multiple events for the same tournament", async () => {
    mockFindMany.mockResolvedValue([
      { id: "e1", sportsSeasonId: SEASON_ID, tournamentId: TOURNAMENT_ID_A, tournament: mockTournamentA },
      { id: "e2", sportsSeasonId: SEASON_ID, tournamentId: TOURNAMENT_ID_A, tournament: mockTournamentA },
      { id: "e3", sportsSeasonId: SEASON_ID, tournamentId: TOURNAMENT_ID_B, tournament: mockTournamentB },
    ]);

    const result = await getTournamentsBySportsSeason(SEASON_ID);

    expect(result).toHaveLength(2);
    expect(result[0].tournamentId).toBe(TOURNAMENT_ID_A);
    expect(result[1].tournamentId).toBe(TOURNAMENT_ID_B);
  });

  it("returns empty array when no events have a tournamentId", async () => {
    mockFindMany.mockResolvedValue([
      { id: "e1", sportsSeasonId: SEASON_ID, tournamentId: null, tournament: null },
    ]);

    const result = await getTournamentsBySportsSeason(SEASON_ID);

    expect(result).toHaveLength(0);
  });

  it("returns empty array when season has no events", async () => {
    mockFindMany.mockResolvedValue([]);

    const result = await getTournamentsBySportsSeason(SEASON_ID);

    expect(result).toHaveLength(0);
  });
});

const SEASON_A_ID = "ss-a";
const SEASON_B_ID = "ss-b";

const mockSeasonA = { id: SEASON_A_ID, name: "Golf June 2026", year: 2026, scoringType: "majors", status: "active", sport: { id: "sp-1", name: "Golf" } };
const mockSeasonB = { id: SEASON_B_ID, name: "Golf Sept 2026", year: 2026, scoringType: "majors", status: "upcoming", sport: { id: "sp-1", name: "Golf" } };

describe("getSportsSeasonsByTournament", () => {
  it("returns one row per unique sports season, deduplicating multiple events in the same season", async () => {
    mockFindMany.mockResolvedValue([
      { id: "e1", sportsSeasonId: SEASON_A_ID, tournamentId: TOURNAMENT_ID_A, sportsSeason: mockSeasonA },
      { id: "e2", sportsSeasonId: SEASON_A_ID, tournamentId: TOURNAMENT_ID_A, sportsSeason: mockSeasonA },
      { id: "e3", sportsSeasonId: SEASON_B_ID, tournamentId: TOURNAMENT_ID_A, sportsSeason: mockSeasonB },
    ]);

    const result = await getSportsSeasonsByTournament(TOURNAMENT_ID_A);

    expect(result).toHaveLength(2);
    expect(result[0].sportsSeasonId).toBe(SEASON_A_ID);
    expect(result[1].sportsSeasonId).toBe(SEASON_B_ID);
  });

  it("returns empty array when no sports seasons use this tournament", async () => {
    mockFindMany.mockResolvedValue([]);

    const result = await getSportsSeasonsByTournament(TOURNAMENT_ID_A);

    expect(result).toHaveLength(0);
  });

  it("passes tournamentId to the query", async () => {
    mockFindMany.mockResolvedValue([]);

    await getSportsSeasonsByTournament(TOURNAMENT_ID_A);

    expect(mockFindMany).toHaveBeenCalledWith(
      expect.objectContaining({
        where: expect.objectContaining({ type: "eq" }),
      })
    );
  });
});
