import { describe, it, expect } from "vitest";
import {
  normalizeTeamName,
  getTeamData,
  eloWinProbability,
} from "../nhl-simulator";

// ─── normalizeTeamName ────────────────────────────────────────────────────────

describe("normalizeTeamName", () => {
  it("lowercases and trims", () => {
    expect(normalizeTeamName("  Colorado Avalanche  ")).toBe("colorado avalanche");
  });

  it("collapses internal whitespace", () => {
    expect(normalizeTeamName("Tampa  Bay  Lightning")).toBe("tampa bay lightning");
  });

  it("is already-normalized identity", () => {
    expect(normalizeTeamName("dallas stars")).toBe("dallas stars");
  });
});

// ─── getTeamData ──────────────────────────────────────────────────────────────

describe("getTeamData", () => {
  it("returns data for an exact match", () => {
    const d = getTeamData("Colorado Avalanche");
    expect(d).toBeDefined();
    expect(d?.conference).toBe("Western");
    expect(d?.division).toBe("Central");
    expect(d?.elo).toBeGreaterThan(1500);
  });

  it("is case-insensitive", () => {
    expect(getTeamData("colorado avalanche")).toEqual(getTeamData("Colorado Avalanche"));
  });

  it("returns undefined for an unknown team", () => {
    expect(getTeamData("Springfield Ice Hounds")).toBeUndefined();
  });

  it("all 32 teams are present", () => {
    const allTeams = [
      // Eastern — Atlantic
      "Tampa Bay Lightning", "Buffalo Sabres", "Montreal Canadiens", "Ottawa Senators",
      "Detroit Red Wings", "Boston Bruins", "Florida Panthers", "Toronto Maple Leafs",
      // Eastern — Metropolitan
      "Carolina Hurricanes", "Columbus Blue Jackets", "Pittsburgh Penguins",
      "New York Islanders", "Philadelphia Flyers", "Washington Capitals",
      "New Jersey Devils", "New York Rangers",
      // Western — Central
      "Colorado Avalanche", "Dallas Stars", "Minnesota Wild", "Utah Mammoth",
      "Nashville Predators", "Winnipeg Jets", "St. Louis Blues", "Chicago Blackhawks",
      // Western — Pacific
      "Anaheim Ducks", "Edmonton Oilers", "Vegas Golden Knights", "Los Angeles Kings",
      "San Jose Sharks", "Seattle Kraken", "Calgary Flames", "Vancouver Canucks",
    ];
    for (const name of allTeams) {
      expect(getTeamData(name), `missing team: ${name}`).toBeDefined();
    }
  });
});

// ─── eloWinProbability ────────────────────────────────────────────────────────

describe("eloWinProbability (PARITY_FACTOR = 1000)", () => {
  it("returns 0.5 for equal Elo ratings", () => {
    expect(eloWinProbability(1500, 1500)).toBeCloseTo(0.5, 6);
  });

  it("favors the higher-rated team", () => {
    expect(eloWinProbability(1594, 1500)).toBeGreaterThan(0.5);
    expect(eloWinProbability(1500, 1594)).toBeLessThan(0.5);
  });

  it("is anti-symmetric: P(A>B) + P(B>A) = 1", () => {
    const p = eloWinProbability(1580, 1520);
    expect(p + eloWinProbability(1520, 1580)).toBeCloseTo(1.0, 10);
  });

  it("a 100-pt gap gives ~55.7% win prob per game", () => {
    // At 1000: P = 1 / (1 + 10^(-100/1000)) ≈ 0.557
    const p = eloWinProbability(1600, 1500);
    expect(p).toBeCloseTo(0.557, 2);
  });

  it("a 200-pt gap gives ~61.3% win prob per game", () => {
    // At 1000: P = 1 / (1 + 10^(-200/1000)) ≈ 0.613
    const p = eloWinProbability(1700, 1500);
    expect(p).toBeCloseTo(0.613, 2);
  });
});

// ─── Seeding probabilities sanity checks ─────────────────────────────────────

describe("team seeding probabilities", () => {
  it("playoff probability sums to ≤ 1.0 per team", () => {
    const teamNames = [
      "Colorado Avalanche", "Dallas Stars", "Minnesota Wild", "Utah Mammoth",
      "Carolina Hurricanes", "Buffalo Sabres", "Tampa Bay Lightning",
    ];
    for (const name of teamNames) {
      const d = getTeamData(name);
      expect(d).toBeDefined();
      const total =
        (d?.p_div1 ?? 0) + (d?.p_div2 ?? 0) + (d?.p_div3 ?? 0) +
        (d?.p_wc1  ?? 0) + (d?.p_wc2  ?? 0);
      expect(total, `${name} playoff prob > 1`).toBeLessThanOrEqual(1.001);
    }
  });

  it("eliminated teams have no seeding probability keys", () => {
    const eliminated = ["Toronto Maple Leafs", "New York Rangers", "Chicago Blackhawks", "Vancouver Canucks"];
    for (const name of eliminated) {
      const d = getTeamData(name);
      expect(d).toBeDefined();
      const total =
        (d?.p_div1 ?? 0) + (d?.p_div2 ?? 0) + (d?.p_div3 ?? 0) +
        (d?.p_wc1  ?? 0) + (d?.p_wc2  ?? 0);
      expect(total, `${name} should have 0 playoff probability`).toBe(0);
    }
  });

  it("division leaders have the highest p_div1 in their division", () => {
    // COL should dominate Central div1
    const col = getTeamData("Colorado Avalanche");
    const dal = getTeamData("Dallas Stars");
    expect((col?.p_div1 ?? 0)).toBeGreaterThan(dal?.p_div1 ?? 0);

    // CAR should dominate Metro div1
    const car = getTeamData("Carolina Hurricanes");
    const cbj = getTeamData("Columbus Blue Jackets");
    expect((car?.p_div1 ?? 0)).toBeGreaterThan(cbj?.p_div1 ?? 0);
  });
});
