import { describe, it, expect } from "vitest";
import {
  computeSeriesScore,
  isSeriesComplete,
  getSeriesLeader,
} from "../playoff-match-game";

const P1 = "participant-1";
const P2 = "participant-2";

const game = (winnerId: string | null, status: "complete" | "scheduled" | "postponed" = "complete") => ({
  winnerId,
  status,
});

describe("computeSeriesScore", () => {
  it("returns zero counts when no games are present", () => {
    const result = computeSeriesScore([], P1, P2);
    expect(result).toEqual({ participant1Wins: 0, participant2Wins: 0, gamesPlayed: 0 });
  });

  it("counts only complete games", () => {
    const games = [
      game(P1, "complete"),
      game(null, "scheduled"),
      game(P2, "postponed"),
    ];
    const result = computeSeriesScore(games, P1, P2);
    expect(result.participant1Wins).toBe(1);
    expect(result.participant2Wins).toBe(0);
    expect(result.gamesPlayed).toBe(1);
  });

  it("correctly tallies a 4-3 series", () => {
    const games = [
      game(P1), game(P2), game(P1), game(P2),
      game(P2), game(P1), game(P1),
    ];
    const result = computeSeriesScore(games, P1, P2);
    expect(result.participant1Wins).toBe(4);
    expect(result.participant2Wins).toBe(3);
    expect(result.gamesPlayed).toBe(7);
  });

  it("ignores games won by unknown participant", () => {
    const games = [game("unknown-team"), game(P1)];
    const result = computeSeriesScore(games, P1, P2);
    expect(result.participant1Wins).toBe(1);
    expect(result.participant2Wins).toBe(0);
    expect(result.gamesPlayed).toBe(2);
  });

  it("handles a sweep correctly", () => {
    const games = [game(P1), game(P1), game(P1), game(P1)];
    const result = computeSeriesScore(games, P1, P2);
    expect(result.participant1Wins).toBe(4);
    expect(result.participant2Wins).toBe(0);
    expect(result.gamesPlayed).toBe(4);
  });
});

describe("isSeriesComplete", () => {
  it("returns false when no games played", () => {
    expect(isSeriesComplete([], P1, P2, 4)).toBe(false);
  });

  it("returns false when neither team has reached required wins", () => {
    const games = [game(P1), game(P1), game(P2)];
    expect(isSeriesComplete(games, P1, P2, 4)).toBe(false);
  });

  it("returns true when participant1 reaches required wins (best of 7)", () => {
    const games = [game(P1), game(P1), game(P1), game(P1)];
    expect(isSeriesComplete(games, P1, P2, 4)).toBe(true);
  });

  it("returns true when participant2 reaches required wins", () => {
    const games = [game(P2), game(P2), game(P2)];
    expect(isSeriesComplete(games, P1, P2, 3)).toBe(true);
  });

  it("works for best of 1", () => {
    expect(isSeriesComplete([game(P1)], P1, P2, 1)).toBe(true);
    expect(isSeriesComplete([], P1, P2, 1)).toBe(false);
  });

  it("works for best of 3", () => {
    const twoToZero = [game(P1), game(P1)];
    expect(isSeriesComplete(twoToZero, P1, P2, 2)).toBe(true);

    const oneToOne = [game(P1), game(P2)];
    expect(isSeriesComplete(oneToOne, P1, P2, 2)).toBe(false);
  });

  it("ignores scheduled/postponed games", () => {
    const games = [game(P1, "complete"), game(P1, "scheduled")];
    expect(isSeriesComplete(games, P1, P2, 2)).toBe(false);
  });
});

describe("getSeriesLeader", () => {
  it("returns null when no games played", () => {
    expect(getSeriesLeader([], P1, P2)).toBeNull();
  });

  it("returns null when tied", () => {
    const games = [game(P1), game(P2)];
    expect(getSeriesLeader(games, P1, P2)).toBeNull();
  });

  it("returns participant1 when they lead", () => {
    const games = [game(P1), game(P1), game(P2)];
    expect(getSeriesLeader(games, P1, P2)).toBe(P1);
  });

  it("returns participant2 when they lead", () => {
    const games = [game(P2), game(P2), game(P1)];
    expect(getSeriesLeader(games, P1, P2)).toBe(P2);
  });

  it("returns correct leader after a sweep", () => {
    const games = [game(P2), game(P2), game(P2), game(P2)];
    expect(getSeriesLeader(games, P1, P2)).toBe(P2);
  });

  it("only counts complete games", () => {
    const games = [game(P2, "complete"), game(P1, "scheduled"), game(P1, "postponed")];
    expect(getSeriesLeader(games, P1, P2)).toBe(P2);
  });
});
