/**
 * Simulator Registry
 *
 * Maps a sport's simulatorType to the appropriate Simulator implementation.
 * Set simulatorType on the sport record in the admin UI.
 * Add new simulators here as new sports are supported.
 */

import type { Simulator } from "./types";
import { BracketSimulator } from "./bracket-simulator";
import { AutoRacingSimulator } from "./auto-racing-simulator";
import { GolfSimulator } from "./golf-simulator";
import { UCLSimulator } from "./ucl-simulator";
import { NCAAMSimulator } from "./ncaam-simulator";
import { NCAAWSimulator } from "./ncaaw-simulator";
import { NBASimulator } from "./nba-simulator";
import { NHLSimulator } from "./nhl-simulator";
import { AFLSimulator } from "./afl-simulator";
import { SnookerSimulator } from "./snooker-simulator";
import { TennisSimulator } from "./tennis-simulator";

export const SIMULATOR_TYPES = [
  "f1_standings",
  "indycar_standings",
  "golf_qualifying_points",
  "playoff_bracket",
  "ucl_bracket",
  "ncaam_bracket",
  "ncaaw_bracket",
  "nba_bracket",
  "nhl_bracket",
  "afl_bracket",
  "snooker_bracket",
  "tennis_qualifying_points",
] as const;

export type SimulatorType = typeof SIMULATOR_TYPES[number];

// ─── Race points tables ───────────────────────────────────────────────────────

/** F1 points: positions 1–10. */
const F1_RACE_POINTS: Record<number, number> = {
  1: 25, 2: 18, 3: 15, 4: 12, 5: 10, 6: 8, 7: 6, 8: 4, 9: 2, 10: 1,
};

/** IndyCar standard race points: positions 1–26. */
const INDYCAR_RACE_POINTS: Record<number, number> = {
  1: 50, 2: 40, 3: 35, 4: 32, 5: 30, 6: 28, 7: 26, 8: 24, 9: 22, 10: 20,
  11: 19, 12: 18, 13: 17, 14: 16, 15: 15, 16: 14, 17: 13, 18: 12, 19: 11, 20: 10,
  21: 9, 22: 8, 23: 7, 24: 6, 25: 5, 26: 5,
};

export interface SimulatorInfo {
  name: string;
  description: string;
}

const REGISTRY: Record<SimulatorType, { info: SimulatorInfo; create: () => Simulator }> = {
  f1_standings: {
    info: { name: "F1 Standings Model", description: "Simulates remaining races using current F1 standings and futures odds" },
    create: () => new AutoRacingSimulator(F1_RACE_POINTS, "f1_standings_model"),
  },
  indycar_standings: {
    info: { name: "IndyCar Standings Model", description: "Simulates remaining races using current IndyCar standings and futures odds" },
    create: () => new AutoRacingSimulator(INDYCAR_RACE_POINTS, "indycar_standings_model"),
  },
  golf_qualifying_points: {
    info: { name: "Qualifying Points Model", description: "Simulates remaining majors using current QP standings and futures odds" },
    create: () => new GolfSimulator(),
  },
  playoff_bracket: {
    info: { name: "Bracket Monte Carlo", description: "Simulates playoff bracket outcomes using Elo ratings" },
    create: () => new BracketSimulator(),
  },
  ucl_bracket: {
    info: { name: "UCL Bracket Monte Carlo", description: "Simulates the UEFA Champions League 16-team knockout bracket using blended Elo + futures odds" },
    create: () => new UCLSimulator(),
  },
  ncaam_bracket: {
    info: { name: "NCAAM Bracket Monte Carlo", description: "Simulates the NCAA Men's Basketball Tournament 64-team bracket using KenPom net ratings" },
    create: () => new NCAAMSimulator(),
  },
  ncaaw_bracket: {
    info: { name: "NCAAW Bracket Monte Carlo", description: "Simulates the NCAA Women's Basketball Tournament 64-team bracket using Barttorvik Barthag ratings" },
    create: () => new NCAAWSimulator(),
  },
  nba_bracket: {
    info: { name: "NBA Playoff Monte Carlo", description: "Simulates NBA playoff seedings (via seed probabilities) and full bracket (best-of-7 series) using Elo ratings" },
    create: () => new NBASimulator(),
  },
  nhl_bracket: {
    info: { name: "NHL Playoff Monte Carlo", description: "Simulates NHL playoff seedings (divisional format, via seed probabilities) and full bracket (best-of-7 series) using Elo ratings" },
    create: () => new NHLSimulator(),
  },
  afl_bracket: {
    info: { name: "AFL Season + Finals Monte Carlo", description: "Projects AFL regular season standings via Elo, then simulates the 10-team finals series (Wildcard → QF/EF → SF → PF → Grand Final). Reads current standings from DB; falls back to full-season projection pre-season." },
    create: () => new AFLSimulator(),
  },
  snooker_bracket: {
    info: { name: "Snooker World Championship Monte Carlo", description: "Simulates the 32-player World Championship bracket using frame-by-frame Bernoulli win probability and direct Elo ratings. Pre-bracket path simulates qualifying (ranks 17-48) and randomly draws qualifiers vs top 16 seeds." },
    create: () => new SnookerSimulator(),
  },
  tennis_qualifying_points: {
    info: { name: "Tennis Grand Slam Monte Carlo", description: "Simulates all 4 Grand Slam majors (128-player seeded bracket) using surface-specific Elo ratings. Accumulates qualifying points per round (tie-split applied) and ranks players by total QP across the season." },
    create: () => new TennisSimulator(),
  },
};

export function getSimulator(simulatorType: SimulatorType): Simulator {
  const entry = REGISTRY[simulatorType];
  if (!entry) {
    throw new Error(
      `No simulator registered for type: "${simulatorType}". ` +
      `Add a simulator to app/services/simulations/registry.ts.`
    );
  }
  return entry.create();
}

export function getSimulatorInfo(simulatorType: SimulatorType): SimulatorInfo | null {
  return REGISTRY[simulatorType]?.info ?? null;
}

