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

/**
 * Tests for proper tournament bracket seeding
 * Phase 2.7 Bug Fix: Ensure proper seeding (1v16, 8v9, etc.) instead of sequential (1v2, 3v4)
 */

/**
 * Helper to simulate the seeding algorithm from playoff-match.ts
 */
function generateStandardSeeding(teamCount: number): [number, number][] {
  if (![4, 8, 16, 32].includes(teamCount)) {
    const pairs: [number, number][] = [];
    for (let i = 0; i < teamCount; i += 2) {
      pairs.push([i, i + 1]);
    }
    return pairs;
  }

  const rounds = Math.log2(teamCount);
  let seeds = [0, 1];

  for (let round = 1; round < rounds; round++) {
    const newSeeds: number[] = [];
    const maxSeed = Math.pow(2, round + 1) - 1;

    for (const seed of seeds) {
      newSeeds.push(seed);
      newSeeds.push(maxSeed - seed);
    }
    seeds = newSeeds;
  }

  const pairs: [number, number][] = [];
  for (let i = 0; i < seeds.length; i += 2) {
    pairs.push([seeds[i], seeds[i + 1]]);
  }

  return pairs;
}

describe("Bracket Seeding", () => {
  describe("4-Team Bracket", () => {
    it("generates correct seeding pairs", () => {
      const pairs = generateStandardSeeding(4);

      // Should be: 1v4, 2v3 (0-indexed: 0v3, 1v2)
      expect(pairs).toEqual([
        [0, 3], // Seed 1 vs Seed 4
        [1, 2], // Seed 2 vs Seed 3
      ]);
    });

    it("balances the bracket", () => {
      const pairs = generateStandardSeeding(4);

      // Top half: seeds 1,4 (sum = 5)
      // Bottom half: seeds 2,3 (sum = 5)
      const topSum = pairs[0][0] + pairs[0][1] + 2; // +2 for 1-indexing
      const bottomSum = pairs[1][0] + pairs[1][1] + 2;

      expect(topSum).toBe(bottomSum);
    });
  });

  describe("8-Team Bracket", () => {
    it("generates correct seeding pairs", () => {
      const pairs = generateStandardSeeding(8);

      // Standard 8-team seeding: 1v8, 4v5, 2v7, 3v6
      expect(pairs).toEqual([
        [0, 7], // Seed 1 vs Seed 8
        [3, 4], // Seed 4 vs Seed 5
        [1, 6], // Seed 2 vs Seed 7
        [2, 5], // Seed 3 vs Seed 6
      ]);
    });

    it("ensures top seeds are separated", () => {
      const pairs = generateStandardSeeding(8);

      // Seeds 1 and 2 should be in different halves
      const match1Seeds = [pairs[0][0] + 1, pairs[0][1] + 1];
      const match2Seeds = [pairs[1][0] + 1, pairs[1][1] + 1];
      const topHalf = [...match1Seeds, ...match2Seeds];

      const match3Seeds = [pairs[2][0] + 1, pairs[2][1] + 1];
      const match4Seeds = [pairs[3][0] + 1, pairs[3][1] + 1];
      const bottomHalf = [...match3Seeds, ...match4Seeds];

      // Seed 1 should be in top half, seed 2 in bottom half (or vice versa)
      expect(topHalf.includes(1) && bottomHalf.includes(2)).toBe(true);
    });
  });

  describe("16-Team Bracket", () => {
    it("generates 8 matches", () => {
      const pairs = generateStandardSeeding(16);
      expect(pairs).toHaveLength(8);
    });

    it("uses all 16 seeds exactly once", () => {
      const pairs = generateStandardSeeding(16);
      const allSeeds = pairs.flat().map(s => s + 1).toSorted((a, b) => a - b);

      expect(allSeeds).toEqual(Array.from({ length: 16 }, (_, i) => i + 1));
    });

    it("ensures seed 1 plays seed 16", () => {
      const pairs = generateStandardSeeding(16);
      const firstMatch = pairs[0];

      // Convert to 1-indexed seeds
      const seed1 = firstMatch[0] + 1;
      const seed2 = firstMatch[1] + 1;

      expect([seed1, seed2].toSorted()).toEqual([1, 16]);
    });

    it("has proper matchup sums for balance", () => {
      const pairs = generateStandardSeeding(16);

      // Each matchup should have a sum that indicates proper seeding
      // 1v16 (sum=17), 2v15 (sum=17), etc.
      const sums = pairs.map(([a, b]) => (a + 1) + (b + 1));

      // All matchups should sum to 17 (n + 1 for 16 teams)
      expect(sums.every(sum => sum === 17)).toBe(true);
    });

    it("balances each quarterfinal pod", () => {
      const pairs = generateStandardSeeding(16);

      // Each pod of 4 teams should have balanced seeds
      // Pod 1 (matches 0,1): 1,16,8,9 sum = 34
      // Pod 2 (matches 2,3): 5,12,4,13 sum = 34
      // Pod 3 (matches 4,5): 6,11,3,14 sum = 34
      // Pod 4 (matches 6,7): 7,10,2,15 sum = 34

      const pod1 = pairs[0].concat(pairs[1]).map(s => s + 1);
      const pod2 = pairs[2].concat(pairs[3]).map(s => s + 1);
      const pod3 = pairs[4].concat(pairs[5]).map(s => s + 1);
      const pod4 = pairs[6].concat(pairs[7]).map(s => s + 1);

      const sum1 = pod1.reduce((a, b) => a + b, 0);
      const sum2 = pod2.reduce((a, b) => a + b, 0);
      const sum3 = pod3.reduce((a, b) => a + b, 0);
      const sum4 = pod4.reduce((a, b) => a + b, 0);

      expect(sum1).toBe(sum2);
      expect(sum2).toBe(sum3);
      expect(sum3).toBe(sum4);
      expect(sum1).toBe(34); // (1+16+8+9)
    });
  });

  describe("32-Team Bracket", () => {
    it("generates 16 matches", () => {
      const pairs = generateStandardSeeding(32);
      expect(pairs).toHaveLength(16);
    });

    it("ensures seed 1 plays seed 32", () => {
      const pairs = generateStandardSeeding(32);
      const firstMatch = pairs[0];

      const seed1 = firstMatch[0] + 1;
      const seed2 = firstMatch[1] + 1;

      expect([seed1, seed2].toSorted()).toEqual([1, 32]);
    });

    it("uses all 32 seeds exactly once", () => {
      const pairs = generateStandardSeeding(32);
      const allSeeds = pairs.flat().map(s => s + 1).toSorted((a, b) => a - b);

      expect(allSeeds).toEqual(Array.from({ length: 32 }, (_, i) => i + 1));
    });
  });

  describe("Non-Standard Sizes", () => {
    it("returns sequential pairs for non-power-of-2 sizes", () => {
      const pairs = generateStandardSeeding(68);

      // For NCAA 68, should return sequential until custom logic is implemented
      expect(pairs[0]).toEqual([0, 1]);
      expect(pairs[1]).toEqual([2, 3]);
      expect(pairs).toHaveLength(34);
    });
  });

  describe("Seed Info Display", () => {
    it("formats seed info correctly for 16-team bracket", () => {
      const pairs = generateStandardSeeding(16);

      // Verify seed info would be displayed correctly (1-indexed for users)
      const match1SeedInfo = `${pairs[0][0] + 1} vs ${pairs[0][1] + 1}`;
      expect(match1SeedInfo).toBe("1 vs 16");

      // Check that all seed info strings are formatted correctly
      const allSeedInfo = pairs.map(([a, b]) => `${a + 1} vs ${b + 1}`);
      expect(allSeedInfo).toHaveLength(8);

      // Each should be "N vs M" format where N + M = 17
      allSeedInfo.forEach(info => {
        expect(info).toMatch(/^\d+ vs \d+$/);
      });
    });
  });
});
