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

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

vi.mock("~/database/schema", () => ({
  sports: {
    name: "sports.name",
    slug: "sports.slug",
    simulatorType: "sports.simulator_type",
    excludeFromHomepage: "sports.exclude_from_homepage",
  },
  sportsSeasons: {
    fantasySeasonId: "sports_seasons.fantasy_season_id",
    status: "sports_seasons.status",
    scoringPattern: "sports_seasons.scoring_pattern",
    scoringType: "sports_seasons.scoring_type",
  },
}));

vi.mock("drizzle-orm", () => ({
  and: (...args: unknown[]) => ({ type: "and", args }),
  eq: (col: unknown, val: unknown) => ({ type: "eq", col, val }),
  isNull: (col: unknown) => ({ type: "isNull", col }),
  ne: (col: unknown, val: unknown) => ({ type: "ne", col, val }),
  sql: (strings: TemplateStringsArray, ...values: unknown[]) => ({ type: "sql", strings, values }),
}));

import { database } from "~/database/context";
import { findPublicSportsWithCurrentSeasons } from "../sport";

function makeSport(overrides: Record<string, unknown> = {}) {
  return {
    id: "sport-1",
    name: "NFL",
    type: "team",
    slug: "nfl",
    description: "Football playoffs.",
    iconUrl: "nfl.svg",
    simulatorType: "nfl_bracket",
    excludeFromHomepage: false,
    createdAt: new Date("2026-01-01T00:00:00Z"),
    updatedAt: new Date("2026-01-01T00:00:00Z"),
    sportsSeasons: [
      {
        id: "season-1",
        name: "NFL 2026",
        year: 2026,
        status: "active",
        scoringPattern: "playoff_bracket",
        scoringType: "playoffs",
      },
    ],
    ...overrides,
  };
}

function makeMockDb(sports: ReturnType<typeof makeSport>[]) {
  return {
    query: {
      sports: {
        findMany: vi.fn().mockResolvedValue(sports),
      },
    },
  };
}

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

describe("findPublicSportsWithCurrentSeasons", () => {
  it("returns non-Brackt sports with active or upcoming global seasons", async () => {
    const mockDb = makeMockDb([
      makeSport(),
      makeSport({
        id: "sport-2",
        name: "Tennis",
        type: "individual",
        slug: "tennis",
        simulatorType: "tennis_qualifying_points",
        sportsSeasons: [
          {
            id: "season-2",
            name: "Tennis 2026",
            year: 2026,
            status: "upcoming",
            scoringPattern: "qualifying_points",
            scoringType: "majors",
          },
        ],
      }),
    ]);
    vi.mocked(database).mockReturnValue(mockDb as never);

    const result = await findPublicSportsWithCurrentSeasons();

    expect(result).toHaveLength(2);
    expect(result[0]).toMatchObject({
      id: "sport-1",
      currentSeasons: [
        {
          id: "season-1",
          name: "NFL 2026",
          year: 2026,
          status: "active",
          scoringPattern: "playoff_bracket",
          scoringType: "playoffs",
        },
      ],
    });
    expect(mockDb.query.sports.findMany).toHaveBeenCalledWith(
      expect.objectContaining({
        with: expect.objectContaining({
          sportsSeasons: expect.objectContaining({
            where: expect.any(Function),
          }),
        }),
      })
    );
  });

  it("excludes sports with no current seasons after the query filter", async () => {
    vi.mocked(database).mockReturnValue(makeMockDb([
      makeSport({ id: "sport-1", sportsSeasons: [] }),
    ]) as never);

    await expect(findPublicSportsWithCurrentSeasons()).resolves.toEqual([]);
  });

  it("excludes Brackt by slug or simulator type", async () => {
    vi.mocked(database).mockReturnValue(makeMockDb([
      makeSport({ id: "brackt-slug", name: "Brackt", slug: "brackt" }),
      makeSport({ id: "brackt-sim", name: "Meta", slug: "meta", simulatorType: "brackt" }),
      makeSport({ id: "sport-2", name: "NHL", slug: "nhl", simulatorType: "nhl_bracket" }),
    ]) as never);

    const result = await findPublicSportsWithCurrentSeasons();

    expect(result.map((sport) => sport.id)).toEqual(["sport-2"]);
  });

  it("excludes sports marked hidden from the public page", async () => {
    vi.mocked(database).mockReturnValue(makeMockDb([
      makeSport({ id: "llws", name: "LLWS", slug: "llws", excludeFromHomepage: true }),
      makeSport({ id: "sport-2", name: "NHL", slug: "nhl", simulatorType: "nhl_bracket" }),
    ]) as never);

    const result = await findPublicSportsWithCurrentSeasons();

    expect(result.map((sport) => sport.id)).toEqual(["sport-2"]);
  });
});
