import { describe, expect, it } from "vitest";
import { bestAetherAssaultRecord, bestBlockbreakerRecords, bestHockeyHealingRecord, highestEndlessBossKillsAfterDefeat, highestRoguelikeRoundAfterDefeat, hockeyPvpRecordAfterMatch } from "./hunterStats";

describe("roguelike hunter records", () => {
  it("records the reached defeat round without lowering a previous best", () => {
    expect(highestRoguelikeRoundAfterDefeat(0, 1)).toBe(1);
    expect(highestRoguelikeRoundAfterDefeat(7, 12)).toBe(12);
    expect(highestRoguelikeRoundAfterDefeat(12, 7)).toBe(12);
  });

  it("normalizes invalid and fractional round values", () => {
    expect(highestRoguelikeRoundAfterDefeat(Number.NaN, Number.NaN)).toBe(1);
    expect(highestRoguelikeRoundAfterDefeat(4.9, 8.9)).toBe(8);
  });
});

describe("Rogue Trials endless hunter records", () => {
  it("keeps the highest boss count from one endless run", () => {
    expect(highestEndlessBossKillsAfterDefeat(0, 17)).toBe(17);
    expect(highestEndlessBossKillsAfterDefeat(17, 9)).toBe(17);
    expect(highestEndlessBossKillsAfterDefeat(17, 23)).toBe(23);
  });

  it("normalizes invalid and fractional kill counts", () => {
    expect(highestEndlessBossKillsAfterDefeat(Number.NaN, Number.NaN)).toBe(0);
    expect(highestEndlessBossKillsAfterDefeat(4.9, 8.9)).toBe(8);
  });
});

describe("Hockey Healing records", () => {
  it("ranks returns first and duration second", () => {
    expect(bestHockeyHealingRecord(12, 90, 13, 70)).toEqual({ returns: 13, durationSeconds: 70 });
    expect(bestHockeyHealingRecord(13, 70, 13, 82)).toEqual({ returns: 13, durationSeconds: 82 });
    expect(bestHockeyHealingRecord(13, 82, 12, 120)).toEqual({ returns: 13, durationSeconds: 82 });
  });

  it("normalizes invalid record values", () => {
    expect(bestHockeyHealingRecord(Number.NaN, Number.NaN, 4.9, 12.5)).toEqual({ returns: 4, durationSeconds: 12.5 });
  });
});

describe("Healing Hockey PVP records", () => {
  it("increments wins and losses independently", () => {
    expect(hockeyPvpRecordAfterMatch(3, 2, true)).toEqual({ wins: 4, losses: 2 });
    expect(hockeyPvpRecordAfterMatch(3, 2, false)).toEqual({ wins: 3, losses: 3 });
  });
});

describe("Blockbreaker records", () => {
  it("keeps bricks, duration, and score as independent lifetime highs", () => {
    expect(bestBlockbreakerRecords(50, 120, 4_000, 60, 90, 3_500)).toEqual({
      bricks: 60,
      durationSeconds: 120,
      score: 4_000,
    });
  });

  it("normalizes invalid and fractional values", () => {
    expect(bestBlockbreakerRecords(Number.NaN, Number.NaN, Number.NaN, 4.9, 12.5, 99.9)).toEqual({
      bricks: 4,
      durationSeconds: 12.5,
      score: 99,
    });
  });
});

describe("Aether Assault records", () => {
  it("keeps wave and duration from the best-score record", () => {
    expect(bestAetherAssaultRecord(10_000, 5, 120, 11_000, 4, 90)).toEqual({ score: 11_000, wave: 4, durationSeconds: 90 });
    expect(bestAetherAssaultRecord(11_000, 4, 90, 11_000, 6, 80)).toEqual({ score: 11_000, wave: 6, durationSeconds: 80 });
    expect(bestAetherAssaultRecord(11_000, 6, 80, 10_500, 9, 200)).toEqual({ score: 11_000, wave: 6, durationSeconds: 80 });
  });

  it("uses duration only after score and wave ties", () => {
    expect(bestAetherAssaultRecord(11_000, 6, 80, 11_000, 6, 95)).toEqual({ score: 11_000, wave: 6, durationSeconds: 95 });
    expect(bestAetherAssaultRecord(Number.NaN, Number.NaN, Number.NaN, 99.9, 3.9, 12.5)).toEqual({ score: 99, wave: 3, durationSeconds: 12.5 });
  });
});
