export interface BracketMatch {
  lid: number;
  round: number;
  order: number | null;
  bye: boolean;
  home_seed?: number;
  away_seed?: number;
  home_from_lid: number | null;
  home_from_loser: boolean;
  away_from_lid: number | null;
  away_from_loser: boolean;
  reset: boolean;
}

export interface BracketTemplate {
  winners: BracketMatch[][];
  losers: BracketMatch[][];
}

export function generateSingleEliminationBracket(teamCount: number): BracketTemplate {
  if (teamCount < 2) {
    throw new Error("Need at least 2 teams for a bracket");
  }

  const nextPowerOf2 = Math.pow(2, Math.ceil(Math.log2(teamCount)));
  const totalRounds = Math.log2(nextPowerOf2);

  const byesNeeded = nextPowerOf2 - teamCount;
  const firstRoundMatches = Math.floor(teamCount / 2);

  const winners: BracketMatch[][] = [];
  let currentLid = 0;
  let currentOrder = 1;

  for (let round = 0; round < totalRounds; round++) {
    const roundMatches: BracketMatch[] = [];
    const matchesInRound = Math.pow(2, totalRounds - round - 1);

    for (let matchIndex = 0; matchIndex < matchesInRound; matchIndex++) {
      const match: BracketMatch = {
        lid: currentLid++,
        round,
        order: currentOrder++,
        bye: false,
        home_from_lid: null,
        home_from_loser: false,
        away_from_lid: null,
        away_from_loser: false,
        reset: false,
      };

      if (round === 0) {
        const homePosition = matchIndex * 2;
        const awayPosition = matchIndex * 2 + 1;

        if (homePosition < teamCount && awayPosition < teamCount) {
          match.home_seed = homePosition + 1;
          match.away_seed = awayPosition + 1;
        } else if (homePosition < teamCount) {
          match.home_seed = homePosition + 1;
          match.bye = true;
        } else {
          match.bye = true;
        }
      } else {
        const prevRound = winners[round - 1];
        const homeFeedIndex = matchIndex * 2;
        const awayFeedIndex = matchIndex * 2 + 1;

        if (homeFeedIndex < prevRound.length) {
          match.home_from_lid = prevRound[homeFeedIndex].lid;
        }
        if (awayFeedIndex < prevRound.length) {
          match.away_from_lid = prevRound[awayFeedIndex].lid;
        }
      }

      roundMatches.push(match);
    }

    winners.push(roundMatches);
  }

  return {
    winners,
    losers: [],
  };
}

export function generateGroupMismatchSeeding(
  numGroups: number,
  teamsPerGroup: number
): number[] {
  const seeding: number[] = [];

  for (let rank = 0; rank < teamsPerGroup; rank++) {
    for (let group = 0; group < numGroups; group++) {
      seeding.push(group * teamsPerGroup + rank);
    }
  }

  return seeding;
}
