/**
 * Bracket Template System
 *
 * Defines pre-configured tournament bracket structures for various sports.
 * Templates specify rounds, match counts, and which rounds contribute to fantasy scoring.
 */

export interface BracketRound {
  /** Display name for this round (e.g., "First Four", "Elite Eight") */
  name: string;
  /** Number of matches in this round */
  matchCount: number;
  /** Name of the round that winners advance to (null for championship) */
  feedsInto: string | null;
  /** Whether this round affects fantasy points (false = 0 points per Q20) */
  isScoring: boolean;
}

export interface GroupStageConfig {
  /** Number of groups */
  groupCount: number;
  /** Teams per group */
  teamsPerGroup: number;
  /** Group labels (e.g., ["A", "B", ..., "L"]) */
  groupLabels: string[];
}

/**
 * A play-in game within a bracket region (e.g., NCAA First Four).
 * Two teams compete; the winner fills a specific seed slot in the main bracket.
 */
export interface BracketPlayIn {
  /** Which seed slot the winner fills (e.g., 11 or 16) */
  seedSlot: number;
  /** Number of teams in this play-in game (always 2) */
  teams: 2;
}

/**
 * A named region within a bracket (e.g., NCAA "East", "South").
 * Each region contributes exactly 16 teams to the Round of 64.
 */
export interface BracketRegion {
  /** Display name (e.g., "East", "South") */
  name: string;
  /**
   * Seed numbers that enter the region directly (no play-in).
   * Must be ascending and contain every seed 1–16 except those covered by playIns.
   * Length = 16 - playIns.length.
   */
  directSeeds: number[];
  /**
   * Play-in games for this region. Order here determines the order their teams
   * appear in the participant array (after all direct-seed teams across all regions).
   */
  playIns: BracketPlayIn[];
}

export interface BracketTemplate {
  /** Unique identifier for this template */
  id: string;
  /** Human-readable name */
  name: string;
  /** Total number of teams in the bracket */
  totalTeams: number;
  /** Ordered list of rounds from earliest to championship */
  rounds: BracketRound[];
  /** Round name where fantasy scoring begins */
  scoringStartsAtRound: string;
  /** Optional group stage configuration (e.g., FIFA World Cup) */
  groupStage?: GroupStageConfig;
  /** Number of teams advancing to knockout stage (when groupStage is defined) */
  knockoutTeams?: number;
  /**
   * Optional named region config. When present, the participant array for bracket
   * generation is structured as: all direct seeds region-by-region in order, then
   * all play-in teams grouped by region (and play-in order within each region).
   */
  regions?: BracketRegion[];
}

/** All seed numbers in a standard 16-team regional bracket (1–16) */
export const ALL_16_SEEDS: number[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16];

// Standard seeding order for a 16-team regional bracket
// Each entry is [higherSeed, lowerSeed] (lower number = better seed)
export const STANDARD_BRACKET_SEEDING: [number, number][] = [
  [1, 16], [8, 9], [5, 12], [4, 13], [6, 11], [3, 14], [7, 10], [2, 15],
];

/**
 * Returns the 0-indexed position within the standard 8-match bracket order
 * for a given seed slot. Used to compute which Round of 64 match a play-in
 * winner advances to.
 *
 * Standard order: 1v16, 8v9, 5v12, 4v13, 6v11, 3v14, 7v10, 2v15
 */
export function matchIndexForSeedSlot(seedSlot: number): number {
  for (let i = 0; i < STANDARD_BRACKET_SEEDING.length; i++) {
    if (STANDARD_BRACKET_SEEDING[i].includes(seedSlot)) return i;
  }
  throw new Error(`Seed slot ${seedSlot} not found in standard bracket seeding`);
}

export interface NCAA68SlotMap {
  /** Start index in participantIds for each region's direct seeds */
  directOffsets: number[];
  /** Ordered list of all play-ins, with participant index info and region context */
  playInOffsets: Array<{
    regionIndex: number;
    playInIndex: number;
    /** Index of the first team in this play-in within participantIds */
    startIndex: number;
    seedSlot: number;
  }>;
  totalDirect: number;
  totalPlayIn: number;
}

/**
 * Computes the participant array slot mapping for an NCAA-style bracket with regions.
 *
 * Participant array layout:
 *   [region 0 direct seeds] [region 1 direct seeds] ... [region N direct seeds]
 *   [region 0 play-in 0 team A, team B] [region 0 play-in 1 team A, team B] ...
 *   [region 1 play-in 0 team A, team B] ...
 *
 * This layout is shared between the server (bracket generation) and the client
 * (form rendering) so both sides agree on which participant{i} maps where.
 */
export function buildNCAA68SlotMap(regions: BracketRegion[]): NCAA68SlotMap {
  let cursor = 0;
  const directOffsets: number[] = [];

  for (const region of regions) {
    directOffsets.push(cursor);
    cursor += region.directSeeds.length;
  }

  const totalDirect = cursor;
  const playInOffsets: NCAA68SlotMap["playInOffsets"] = [];

  for (let r = 0; r < regions.length; r++) {
    for (let p = 0; p < regions[r].playIns.length; p++) {
      playInOffsets.push({
        regionIndex: r,
        playInIndex: p,
        startIndex: cursor,
        seedSlot: regions[r].playIns[p].seedSlot,
      });
      cursor += 2;
    }
  }

  const totalPlayIn = cursor - totalDirect;

  return { directOffsets, playInOffsets, totalDirect, totalPlayIn };
}

/**
 * Simple 4-team bracket
 * Semifinals → Finals
 * All rounds score fantasy points
 */
export const SIMPLE_4: BracketTemplate = {
  id: "simple_4",
  name: "Simple 4-Team Bracket",
  totalTeams: 4,
  scoringStartsAtRound: "Semifinals",
  rounds: [
    {
      name: "Semifinals",
      matchCount: 2,
      feedsInto: "Finals",
      isScoring: true, // Losers share 3rd-4th
    },
    {
      name: "Finals",
      matchCount: 1,
      feedsInto: null,
      isScoring: true, // Winner 1st, Loser 2nd
    },
  ],
};

/**
 * Simple 8-team bracket
 * Quarterfinals → Semifinals → Finals
 * All rounds score fantasy points
 */
export const SIMPLE_8: BracketTemplate = {
  id: "simple_8",
  name: "Simple 8-Team Bracket",
  totalTeams: 8,
  scoringStartsAtRound: "Quarterfinals",
  rounds: [
    {
      name: "Quarterfinals",
      matchCount: 4,
      feedsInto: "Semifinals",
      isScoring: true, // Losers share 5th-8th
    },
    {
      name: "Semifinals",
      matchCount: 2,
      feedsInto: "Finals",
      isScoring: true, // Losers share 3rd-4th
    },
    {
      name: "Finals",
      matchCount: 1,
      feedsInto: null,
      isScoring: true, // Winner 1st, Loser 2nd
    },
  ],
};

/**
 * Simple 16-team bracket
 * Round of 16 → Quarterfinals → Semifinals → Finals
 * Only Quarterfinals and beyond score points (top 8)
 */
export const SIMPLE_16: BracketTemplate = {
  id: "simple_16",
  name: "Simple 16-Team Bracket",
  totalTeams: 16,
  scoringStartsAtRound: "Quarterfinals",
  rounds: [
    {
      name: "Round of 16",
      matchCount: 8,
      feedsInto: "Quarterfinals",
      isScoring: false, // Early elimination = 0 points
    },
    {
      name: "Quarterfinals",
      matchCount: 4,
      feedsInto: "Semifinals",
      isScoring: true, // Losers share 5th-8th
    },
    {
      name: "Semifinals",
      matchCount: 2,
      feedsInto: "Finals",
      isScoring: true, // Losers share 3rd-4th
    },
    {
      name: "Finals",
      matchCount: 1,
      feedsInto: null,
      isScoring: true, // Winner 1st, Loser 2nd
    },
  ],
};

/**
 * Simple 32-team bracket
 * Round of 32 → Round of 16 → Quarterfinals → Semifinals → Finals
 * Only Quarterfinals and beyond score points (top 8)
 */
export const SIMPLE_32: BracketTemplate = {
  id: "simple_32",
  name: "Simple 32-Team Bracket",
  totalTeams: 32,
  scoringStartsAtRound: "Quarterfinals",
  rounds: [
    {
      name: "Round of 32",
      matchCount: 16,
      feedsInto: "Round of 16",
      isScoring: false, // Early elimination = 0 points
    },
    {
      name: "Round of 16",
      matchCount: 8,
      feedsInto: "Quarterfinals",
      isScoring: false, // Early elimination = 0 points
    },
    {
      name: "Quarterfinals",
      matchCount: 4,
      feedsInto: "Semifinals",
      isScoring: true, // Losers share 5th-8th
    },
    {
      name: "Semifinals",
      matchCount: 2,
      feedsInto: "Finals",
      isScoring: true, // Losers share 3rd-4th
    },
    {
      name: "Finals",
      matchCount: 1,
      feedsInto: null,
      isScoring: true, // Winner 1st, Loser 2nd
    },
  ],
};

/**
 * NCAA March Madness (68 teams)
 * First Four (play-in) → Round of 64 → Round of 32 → Sweet Sixteen → Elite Eight → Final Four → Championship
 * Only Elite Eight and beyond score points per Q18
 *
 * 2026 region config:
 *   East    — 16 direct seeds, no play-ins
 *   South   — 15 direct seeds, 16-seed play-in
 *   West    — 15 direct seeds, 11-seed play-in
 *   Midwest — 14 direct seeds, 11-seed play-in + 16-seed play-in
 *
 * Participant array layout (68 slots):
 *   [0–15]   East seeds 1–16
 *   [16–30]  South seeds 1–15
 *   [31–45]  West seeds 1–10, 12–16
 *   [46–59]  Midwest seeds 1–10, 12–15
 *   [60–61]  South 16-seed play-in (2 teams)
 *   [62–63]  West 11-seed play-in (2 teams)
 *   [64–65]  Midwest 11-seed play-in (2 teams)
 *   [66–67]  Midwest 16-seed play-in (2 teams)
 */
export const NCAA_68: BracketTemplate = {
  id: "ncaa_68",
  name: "NCAA March Madness (68 teams)",
  totalTeams: 68,
  scoringStartsAtRound: "Elite Eight",
  rounds: [
    {
      name: "First Four",
      matchCount: 4,
      feedsInto: "Round of 64",
      isScoring: false, // Play-in games don't score
    },
    {
      name: "Round of 64",
      matchCount: 32,
      feedsInto: "Round of 32",
      isScoring: false,
    },
    {
      name: "Round of 32",
      matchCount: 16,
      feedsInto: "Sweet Sixteen",
      isScoring: false,
    },
    {
      name: "Sweet Sixteen",
      matchCount: 8,
      feedsInto: "Elite Eight",
      isScoring: false,
    },
    {
      name: "Elite Eight",
      matchCount: 4,
      feedsInto: "Final Four",
      isScoring: true, // Losers share 5th-8th
    },
    {
      name: "Final Four",
      matchCount: 2,
      feedsInto: "Championship",
      isScoring: true, // Losers share 3rd-4th
    },
    {
      name: "Championship",
      matchCount: 1,
      feedsInto: null,
      isScoring: true, // Winner 1st, Loser 2nd
    },
  ],
  regions: [
    {
      // East: all 16 seeds enter directly — no play-in games
      name: "East",
      directSeeds: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
      playIns: [],
    },
    {
      // South: seeds 1–15 direct; 16-seed determined by First Four play-in
      name: "South",
      directSeeds: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
      playIns: [{ seedSlot: 16, teams: 2 }],
    },
    {
      // West: seeds 1–10 and 12–16 direct; 11-seed determined by First Four play-in
      name: "West",
      directSeeds: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 13, 14, 15, 16],
      playIns: [{ seedSlot: 11, teams: 2 }],
    },
    {
      // Midwest: seeds 1–10 and 12–15 direct; both 11-seed and 16-seed via play-ins
      name: "Midwest",
      directSeeds: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 13, 14, 15],
      playIns: [
        { seedSlot: 11, teams: 2 },
        { seedSlot: 16, teams: 2 },
      ],
    },
  ],
};

/**
 * NFL Playoffs (14 teams)
 * Wild Card → Divisional → Conference Championship → Super Bowl
 * Top 2 seeds get byes (skip Wild Card)
 * Scoring starts at Divisional (top 8)
 */
export const NFL_14: BracketTemplate = {
  id: "nfl_14",
  name: "NFL Playoffs (14 teams)",
  totalTeams: 14,
  scoringStartsAtRound: "Divisional",
  rounds: [
    {
      name: "Wild Card",
      matchCount: 6,
      feedsInto: "Divisional",
      isScoring: false, // 12 teams play, 2 have byes
    },
    {
      name: "Divisional",
      matchCount: 4,
      feedsInto: "Conference Championship",
      isScoring: true, // Quarterfinals - Losers share 5th-8th
    },
    {
      name: "Conference Championship",
      matchCount: 2,
      feedsInto: "Super Bowl",
      isScoring: true, // Semifinals - Losers share 3rd-4th
    },
    {
      name: "Super Bowl",
      matchCount: 1,
      feedsInto: null,
      isScoring: true, // Finals - Winner 1st, Loser 2nd
    },
  ],
};

/**
 * AFL Finals (10 teams with Wildcard Round from 2026)
 * Complex bracket with double-chance system for top 6 teams
 *
 * Structure:
 * - Wildcard Round: 7v10, 8v9 (losers eliminated with 0 points)
 * - Week 1 Finals:
 *   - Qualifying Finals: 1v4, 2v3 (losers get second chance)
 *   - Elimination Finals: 5v8(wildcard winner), 6v7(wildcard winner) (losers share 7th-8th)
 * - Week 2: Semi-Finals (QF losers vs EF winners, losers share 5th-6th)
 * - Week 3: Preliminary Finals (QF winners vs SF winners, losers share 3rd-4th)
 * - Week 4: Grand Final (1st vs 2nd)
 *
 * Note: This is NOT a simple single-elimination tree - it has double-chance paths
 */
export const AFL_10: BracketTemplate = {
  id: "afl_10",
  name: "AFL Finals (10 teams with Wildcard)",
  totalTeams: 10,
  scoringStartsAtRound: "Elimination Finals",
  rounds: [
    {
      name: "Wildcard Round",
      matchCount: 2,
      feedsInto: "Elimination Finals",
      isScoring: false, // Losers get 0 points (9th-10th)
    },
    {
      name: "Qualifying Finals",
      matchCount: 2,
      feedsInto: "Preliminary Finals", // Winners get bye
      isScoring: false, // Losers get second chance (go to Semi-Finals)
    },
    {
      name: "Elimination Finals",
      matchCount: 2,
      feedsInto: "Semi-Finals",
      isScoring: true, // Losers share 7th-8th
    },
    {
      name: "Semi-Finals",
      matchCount: 2,
      feedsInto: "Preliminary Finals",
      isScoring: true, // Losers share 5th-6th
    },
    {
      name: "Preliminary Finals",
      matchCount: 2,
      feedsInto: "Grand Final",
      isScoring: true, // Losers share 3rd-4th
    },
    {
      name: "Grand Final",
      matchCount: 1,
      feedsInto: null,
      isScoring: true, // Winner 1st, Loser 2nd
    },
  ],
};

/**
 * FIFA World Cup 48-team tournament (2026+)
 * Group stage: 12 groups of 4 teams play round-robin
 * Knockout stage: 32 teams advance to single-elimination bracket
 *
 * Group-to-knockout advancement is fully manual.
 * Admin marks teams as eliminated from groups, then assigns 32 advancing
 * teams into knockout bracket slots.
 *
 * Only knockout stage awards fantasy points.
 * Teams eliminated in groups get finalPosition = 0.
 */
export const FIFA_48: BracketTemplate = {
  id: "fifa_48",
  name: "FIFA World Cup (48 teams)",
  totalTeams: 48,
  knockoutTeams: 32,
  scoringStartsAtRound: "Quarterfinals",
  groupStage: {
    groupCount: 12,
    teamsPerGroup: 4,
    groupLabels: ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L"],
  },
  rounds: [
    {
      name: "Round of 32",
      matchCount: 16,
      feedsInto: "Round of 16",
      isScoring: false,
    },
    {
      name: "Round of 16",
      matchCount: 8,
      feedsInto: "Quarterfinals",
      isScoring: false,
    },
    {
      name: "Quarterfinals",
      matchCount: 4,
      feedsInto: "Semifinals",
      isScoring: true,
    },
    {
      name: "Semifinals",
      matchCount: 2,
      feedsInto: "Finals",
      isScoring: true,
    },
    {
      name: "Finals",
      matchCount: 1,
      feedsInto: null,
      isScoring: true,
    },
  ],
};

/**
 * All available bracket templates
 */
export const BRACKET_TEMPLATES: Record<string, BracketTemplate> = {
  simple_4: SIMPLE_4,
  simple_8: SIMPLE_8,
  simple_16: SIMPLE_16,
  simple_32: SIMPLE_32,
  ncaa_68: NCAA_68,
  nfl_14: NFL_14,
  afl_10: AFL_10,
  fifa_48: FIFA_48,
};

/**
 * Get a bracket template by ID
 */
export function getBracketTemplate(id: string): BracketTemplate | undefined {
  return BRACKET_TEMPLATES[id];
}

/**
 * Get all bracket templates as an array
 */
export function getAllBracketTemplates(): BracketTemplate[] {
  return Object.values(BRACKET_TEMPLATES);
}

/**
 * Returns round names in chronological order (earliest first) for the given matches.
 * When a template is provided its defined order is used; otherwise rounds are sorted
 * by descending match count (more matches = earlier round).
 */
export function getOrderedRoundsFromMatches(
  matches: Array<{ round: string }>,
  template?: BracketTemplate
): string[] {
  const roundsInMatches = new Set(matches.map((m) => m.round));

  if (template) {
    return template.rounds
      .map((r) => r.name)
      .filter((name) => roundsInMatches.has(name));
  }

  const roundMatchCounts = new Map<string, number>();
  for (const m of matches) {
    roundMatchCounts.set(m.round, (roundMatchCounts.get(m.round) || 0) + 1);
  }
  return Array.from(roundMatchCounts.keys()).toSorted(
    (a, b) => (roundMatchCounts.get(b) || 0) - (roundMatchCounts.get(a) || 0)
  );
}

/**
 * Helper to determine scoring round type based on match count in scoring rounds
 * Used for determining placement sharing (5-8th, 3-4th, 1-2nd)
 *
 * Special handling for AFL finals system which has specific placement rules
 */
export function getScoringRoundType(
  roundName: string,
  template: BracketTemplate
): "quarterfinals" | "semifinals" | "finals" | null {
  const round = template.rounds.find((r) => r.name === roundName);
  if (!round || !round.isScoring) return null;

  // Special handling for AFL finals
  if (template.id === "afl_10") {
    if (roundName === "Elimination Finals") return "quarterfinals"; // Losers share 7-8th
    if (roundName === "Semi-Finals") return "quarterfinals"; // Losers share 5-6th (custom mapping)
    if (roundName === "Preliminary Finals") return "semifinals"; // Losers share 3-4th
    if (roundName === "Grand Final") return "finals"; // 1st and 2nd
    return null;
  }

  // Standard logic for other templates
  // Determine type by match count in scoring round
  if (round.matchCount === 4) return "quarterfinals"; // 8 teams, losers share 5-8th
  if (round.matchCount === 2) return "semifinals"; // 4 teams, losers share 3-4th
  if (round.matchCount === 1) return "finals"; // 2 teams, 1st and 2nd
  return null;
}
