import { describe, it, expect } from "vitest";
import { buildDraftOrderTeams, getTeamForPick, getProjectedPicks } from "~/lib/draft-order";

describe("buildDraftOrderTeams", () => {
  const teams = [
    { id: "t1" }, { id: "t2" }, { id: "t3" },
  ];

  it("returns all teams in natural order when no slots exist", () => {
    expect(buildDraftOrderTeams([], teams)).toEqual(["t1", "t2", "t3"]);
  });

  it("returns slot order when all teams are slotted", () => {
    const slots = [{ teamId: "t3" }, { teamId: "t1" }, { teamId: "t2" }];
    expect(buildDraftOrderTeams(slots, teams)).toEqual(["t3", "t1", "t2"]);
  });

  it("appends unslotted teams after slotted ones in partial state", () => {
    const slots = [{ teamId: "t2" }];
    expect(buildDraftOrderTeams(slots, teams)).toEqual(["t2", "t1", "t3"]);
  });

  it("returns empty array when both slots and teams are empty", () => {
    expect(buildDraftOrderTeams([], [])).toEqual([]);
  });
});

function makeSlots(teamCount: number) {
  return Array.from({ length: teamCount }, (_, i) => ({
    draftOrder: i + 1,
    teamId: `team-${i + 1}`,
  }));
}

describe("getTeamForPick", () => {
  const slots = makeSlots(4);

  it("returns correct team for round 1 (forward)", () => {
    expect(getTeamForPick(1, slots)?.teamId).toBe("team-1");
    expect(getTeamForPick(2, slots)?.teamId).toBe("team-2");
    expect(getTeamForPick(3, slots)?.teamId).toBe("team-3");
    expect(getTeamForPick(4, slots)?.teamId).toBe("team-4");
  });

  it("returns correct team for round 2 (snake reversed)", () => {
    expect(getTeamForPick(5, slots)?.teamId).toBe("team-4");
    expect(getTeamForPick(6, slots)?.teamId).toBe("team-3");
    expect(getTeamForPick(7, slots)?.teamId).toBe("team-2");
    expect(getTeamForPick(8, slots)?.teamId).toBe("team-1");
  });

  it("returns correct team for round 3 (forward again)", () => {
    expect(getTeamForPick(9, slots)?.teamId).toBe("team-1");
    expect(getTeamForPick(10, slots)?.teamId).toBe("team-2");
    expect(getTeamForPick(11, slots)?.teamId).toBe("team-3");
    expect(getTeamForPick(12, slots)?.teamId).toBe("team-4");
  });

  it("returns undefined for empty slots", () => {
    expect(getTeamForPick(1, [])).toBeUndefined();
  });
});

describe("getProjectedPicks", () => {
  it("returns empty array when no draft slots", () => {
    const result = getProjectedPicks({
      draftSlots: [],
      userTeamId: "team-1",
      currentPick: 1,
      totalRounds: 10,
      existingPicks: [],
    });
    expect(result).toEqual([]);
  });

  it("returns empty array when user has no team in slots", () => {
    const result = getProjectedPicks({
      draftSlots: makeSlots(4),
      userTeamId: "team-999",
      currentPick: 1,
      totalRounds: 10,
      existingPicks: [],
    });
    expect(result).toEqual([]);
  });

  describe("4-team snake draft, user at position 1", () => {
    const slots = makeSlots(4);

    it("computes picks from start of draft", () => {
      const result = getProjectedPicks({
        draftSlots: slots,
        userTeamId: "team-1",
        currentPick: 1,
        totalRounds: 4,
        existingPicks: [],
      });

      expect(result).toEqual([
        { round: 1, pickNumber: 1, picksFromNow: 0 },
        { round: 2, pickNumber: 8, picksFromNow: 7 },
        { round: 3, pickNumber: 9, picksFromNow: 8 },
        { round: 4, pickNumber: 16, picksFromNow: 15 },
      ]);
    });

    it("computes picks from mid-draft, skipping past picks", () => {
      const result = getProjectedPicks({
        draftSlots: slots,
        userTeamId: "team-1",
        currentPick: 5,
        totalRounds: 4,
        existingPicks: [
          { pickNumber: 1, teamId: "team-1" },
        ],
      });

      expect(result).toEqual([
        { round: 2, pickNumber: 8, picksFromNow: 3 },
        { round: 3, pickNumber: 9, picksFromNow: 4 },
        { round: 4, pickNumber: 16, picksFromNow: 11 },
      ]);
    });

    it("skips rounds already picked even if current pick is before them", () => {
      const result = getProjectedPicks({
        draftSlots: slots,
        userTeamId: "team-1",
        currentPick: 1,
        totalRounds: 4,
        existingPicks: [
          { pickNumber: 1, teamId: "team-1" },
          { pickNumber: 8, teamId: "team-1" },
        ],
      });

      expect(result).toEqual([
        { round: 3, pickNumber: 9, picksFromNow: 8 },
        { round: 4, pickNumber: 16, picksFromNow: 15 },
      ]);
    });
  });

  describe("4-team snake draft, user at position 3", () => {
    const slots = makeSlots(4);

    it("computes correct snake positions", () => {
      const result = getProjectedPicks({
        draftSlots: slots,
        userTeamId: "team-3",
        currentPick: 1,
        totalRounds: 4,
        existingPicks: [],
      });

      expect(result).toEqual([
        { round: 1, pickNumber: 3, picksFromNow: 2 },
        { round: 2, pickNumber: 6, picksFromNow: 5 },
        { round: 3, pickNumber: 11, picksFromNow: 10 },
        { round: 4, pickNumber: 14, picksFromNow: 13 },
      ]);
    });
  });

  describe("4-team snake draft, user at position 4 (last)", () => {
    const slots = makeSlots(4);

    it("picks first in round 2 due to snake reversal", () => {
      const result = getProjectedPicks({
        draftSlots: slots,
        userTeamId: "team-4",
        currentPick: 1,
        totalRounds: 4,
        existingPicks: [],
      });

      expect(result).toEqual([
        { round: 1, pickNumber: 4, picksFromNow: 3 },
        { round: 2, pickNumber: 5, picksFromNow: 4 },
        { round: 3, pickNumber: 12, picksFromNow: 11 },
        { round: 4, pickNumber: 13, picksFromNow: 12 },
      ]);
    });
  });

  it("returns empty when all picks are in the past", () => {
    const result = getProjectedPicks({
      draftSlots: makeSlots(4),
      userTeamId: "team-1",
      currentPick: 17,
      totalRounds: 4,
      existingPicks: [
        { pickNumber: 1, teamId: "team-1" },
        { pickNumber: 8, teamId: "team-1" },
        { pickNumber: 9, teamId: "team-1" },
        { pickNumber: 16, teamId: "team-1" },
      ],
    });
    expect(result).toEqual([]);
  });

  it("handles 8-team snake draft correctly", () => {
    const slots = makeSlots(8);

    const result = getProjectedPicks({
      draftSlots: slots,
      userTeamId: "team-5",
      currentPick: 1,
      totalRounds: 3,
      existingPicks: [],
    });

    expect(result).toEqual([
      { round: 1, pickNumber: 5, picksFromNow: 4 },
      { round: 2, pickNumber: 12, picksFromNow: 11 },
      { round: 3, pickNumber: 21, picksFromNow: 20 },
    ]);
  });

  it("excludes picks before currentPick", () => {
    const result = getProjectedPicks({
      draftSlots: makeSlots(4),
      userTeamId: "team-1",
      currentPick: 9,
      totalRounds: 4,
      existingPicks: [],
    });

    expect(result).toEqual([
      { round: 3, pickNumber: 9, picksFromNow: 0 },
      { round: 4, pickNumber: 16, picksFromNow: 7 },
    ]);
  });
});
