export interface PlayerPropMarketDefinition {
  statType: string;
  label: string;
  aliases: string[];
  theOddsMarketKey?: string | null;
  sortWeight?: number;
  fallbackDelta?: number;
}

type LeagueRegistry = Record<string, PlayerPropMarketDefinition[]>;

const PLAYER_PROP_MARKET_REGISTRY: LeagueRegistry = {
  nba: [
    { statType: 'points', label: 'Points', aliases: ['points', 'point'], theOddsMarketKey: 'player_points', sortWeight: 1, fallbackDelta: 2.5 },
    { statType: 'rebounds', label: 'Rebounds', aliases: ['rebounds', 'rebound'], theOddsMarketKey: 'player_rebounds', sortWeight: 2, fallbackDelta: 1.5 },
    { statType: 'assists', label: 'Assists', aliases: ['assists', 'assist'], theOddsMarketKey: 'player_assists', sortWeight: 3, fallbackDelta: 1.2 },
    { statType: 'threes', label: '3PT Made', aliases: ['threes', 'threepointersmade', 'three_pointers_made', '3pm', 'threemade', 'threesmade'], theOddsMarketKey: 'player_threes', sortWeight: 4, fallbackDelta: 0.8 },
    { statType: 'blocks', label: 'Blocks', aliases: ['blocks', 'block'], theOddsMarketKey: 'player_blocks', sortWeight: 5, fallbackDelta: 0.4 },
    { statType: 'steals', label: 'Steals', aliases: ['steals', 'steal'], theOddsMarketKey: 'player_steals', sortWeight: 6, fallbackDelta: 0.4 },
    { statType: 'turnovers', label: 'Turnovers', aliases: ['turnovers', 'turnover'], theOddsMarketKey: 'player_turnovers', sortWeight: 7, fallbackDelta: 0.8 },
    { statType: 'pointsreboundsassists', label: 'Pts + Reb + Ast', aliases: ['pointsreboundsassists', 'points+rebounds+assists', 'pra'], theOddsMarketKey: 'player_points_rebounds_assists', sortWeight: 8, fallbackDelta: 3.5 },
    { statType: 'pointsrebounds', label: 'Pts + Reb', aliases: ['pointsrebounds', 'points+rebounds', 'pr'], theOddsMarketKey: 'player_points_rebounds', sortWeight: 9, fallbackDelta: 3.0 },
    { statType: 'pointsassists', label: 'Pts + Ast', aliases: ['pointsassists', 'points+assists', 'pa'], theOddsMarketKey: 'player_points_assists', sortWeight: 10, fallbackDelta: 2.8 },
    { statType: 'reboundsassists', label: 'Reb + Ast', aliases: ['reboundsassists', 'rebounds+assists', 'ra'], theOddsMarketKey: 'player_rebounds_assists', sortWeight: 11, fallbackDelta: 2.4 },
  ],
  ncaab: [
    { statType: 'points', label: 'Points', aliases: ['points', 'point'], theOddsMarketKey: 'player_points', sortWeight: 1, fallbackDelta: 2.2 },
    { statType: 'rebounds', label: 'Rebounds', aliases: ['rebounds', 'rebound'], theOddsMarketKey: 'player_rebounds', sortWeight: 2, fallbackDelta: 1.4 },
    { statType: 'assists', label: 'Assists', aliases: ['assists', 'assist'], theOddsMarketKey: 'player_assists', sortWeight: 3, fallbackDelta: 1.0 },
    { statType: 'threes', label: '3PT Made', aliases: ['threes', 'threepointersmade', 'three_pointers_made', '3pm', 'threemade', 'threesmade'], theOddsMarketKey: 'player_threes', sortWeight: 4, fallbackDelta: 0.7 },
  ],
  wnba: [
    { statType: 'points', label: 'Points', aliases: ['points', 'point'], theOddsMarketKey: 'player_points', sortWeight: 1, fallbackDelta: 2.1 },
    { statType: 'rebounds', label: 'Rebounds', aliases: ['rebounds', 'rebound'], theOddsMarketKey: 'player_rebounds', sortWeight: 2, fallbackDelta: 1.3 },
    { statType: 'assists', label: 'Assists', aliases: ['assists', 'assist'], theOddsMarketKey: 'player_assists', sortWeight: 3, fallbackDelta: 1.0 },
    { statType: 'threes', label: '3PT Made', aliases: ['threes', 'threepointersmade', 'three_pointers_made', '3pm', 'threemade', 'threesmade'], theOddsMarketKey: 'player_threes', sortWeight: 4, fallbackDelta: 0.7 },
    { statType: 'blocks', label: 'Blocks', aliases: ['blocks', 'block'], theOddsMarketKey: 'player_blocks', sortWeight: 5, fallbackDelta: 0.4 },
    { statType: 'steals', label: 'Steals', aliases: ['steals', 'steal'], theOddsMarketKey: 'player_steals', sortWeight: 6, fallbackDelta: 0.4 },
    { statType: 'turnovers', label: 'Turnovers', aliases: ['turnovers', 'turnover'], theOddsMarketKey: 'player_turnovers', sortWeight: 7, fallbackDelta: 0.7 },
  ],
  mlb: [
    { statType: 'batting_hits', label: 'Hits', aliases: ['battinghits', 'batting_hits', 'hit', 'hits'], theOddsMarketKey: 'batter_hits' },
    { statType: 'batting_totalBases', label: 'Total Bases', aliases: ['battingtotalbases', 'batting_total_bases', 'totalbase', 'totalbases'], theOddsMarketKey: 'batter_total_bases' },
    { statType: 'batting_homeRuns', label: 'Home Runs', aliases: ['battinghomeruns', 'batting_home_runs', 'homerun', 'homeruns', 'home_run', 'home_runs'], theOddsMarketKey: 'batter_home_runs' },
    { statType: 'batting_runs', label: 'Runs', aliases: ['battingruns', 'batting_runs', 'run', 'runs', 'point', 'points'], theOddsMarketKey: 'batter_runs_scored' },
    { statType: 'batting_RBI', label: 'RBIs', aliases: ['battingrbi', 'batting_rbi', 'rbi', 'rbis'], theOddsMarketKey: 'batter_rbis' },
    { statType: 'batting_hits+runs+rbi', label: 'Hits + Runs + RBIs', aliases: ['battinghitsrunsrbi', 'batting_hits_runs_rbi', 'batting_hits+runs+rbi', 'hitsrunsrbis'], theOddsMarketKey: 'batter_hits_runs_rbis' },
    { statType: 'batting_singles', label: 'Singles', aliases: ['battingsingles', 'batting_singles'], theOddsMarketKey: 'batter_singles' },
    { statType: 'batting_doubles', label: 'Doubles', aliases: ['battingdoubles', 'batting_doubles'], theOddsMarketKey: 'batter_doubles' },
    { statType: 'batting_triples', label: 'Triples', aliases: ['battingtriples', 'batting_triples'], theOddsMarketKey: 'batter_triples' },
    { statType: 'batting_basesOnBalls', label: 'Walks', aliases: ['battingbasesonballs', 'batting_base_on_balls', 'batting_walks', 'battingwalks', 'walks'], theOddsMarketKey: 'batter_walks' },
    { statType: 'batting_strikeouts', label: 'Strikeouts', aliases: ['battingstrikeouts', 'batting_strikeouts', 'strikeout', 'strikeouts'], theOddsMarketKey: 'batter_strikeouts' },
    { statType: 'batting_stolenBases', label: 'Stolen Bases', aliases: ['battingstolenbases', 'batting_stolen_bases', 'stolenbases'], theOddsMarketKey: 'batter_stolen_bases' },
    { statType: 'pitching_strikeouts', label: 'Strikeouts', aliases: ['pitchingstrikeouts', 'pitching_strikeouts', 'pitcherstrikeouts', 'pitcher_strikeouts'], theOddsMarketKey: 'pitcher_strikeouts' },
    { statType: 'pitching_hits', label: 'Hits Allowed', aliases: ['pitchinghits', 'pitching_hits', 'hitsallowed', 'hitallowed', 'pitcherhitsallowed'], theOddsMarketKey: 'pitcher_hits_allowed' },
    { statType: 'pitching_basesOnBalls', label: 'Walks Allowed', aliases: ['pitchingbasesonballs', 'pitching_walks', 'pitchingwalks', 'walksallowed', 'walkallowed', 'pitcherwalks'], theOddsMarketKey: 'pitcher_walks' },
    { statType: 'pitching_earnedRuns', label: 'Earned Runs', aliases: ['pitchingearnedruns', 'pitching_earned_runs', 'earnedrun', 'earnedruns'], theOddsMarketKey: 'pitcher_earned_runs' },
    { statType: 'pitching_outs', label: 'Outs Recorded', aliases: ['pitchingouts', 'pitching_outs', 'outsrecorded', 'outs'], theOddsMarketKey: 'pitcher_outs' },
  ],
  nhl: [
    { statType: 'shots_onGoal', label: 'Shots on Goal', aliases: ['shotsongoal', 'shots_on_goal', 'shotongoal', 'sog', 'shots'], theOddsMarketKey: 'player_shots_on_goal', sortWeight: 1, fallbackDelta: 0.6 },
    { statType: 'points', label: 'Points', aliases: ['points', 'point'], theOddsMarketKey: 'player_points', sortWeight: 2, fallbackDelta: 0.5 },
    { statType: 'assists', label: 'Assists', aliases: ['assists', 'assist'], theOddsMarketKey: 'player_assists', sortWeight: 3, fallbackDelta: 0.4 },
    { statType: 'goalie_saves', label: 'Saves', aliases: ['goaliesaves', 'goalie_saves', 'saves', 'save'], theOddsMarketKey: 'player_total_saves', sortWeight: 4, fallbackDelta: 2.5 },
    { statType: 'goals', label: 'Goals', aliases: ['goals', 'goal'], theOddsMarketKey: 'player_goals', sortWeight: 5, fallbackDelta: 0.3 },
  ],
  epl: [
    { statType: 'shots', label: 'Shots', aliases: ['shots', 'shot'], theOddsMarketKey: 'player_shots', sortWeight: 1, fallbackDelta: 0.8 },
    { statType: 'shots_onTarget', label: 'Shots on Target', aliases: ['shotsontarget', 'shots_on_target', 'shotontarget', 'sot'], theOddsMarketKey: 'player_shots_on_target', sortWeight: 2, fallbackDelta: 0.4 },
    { statType: 'goals', label: 'Goals', aliases: ['goals', 'goal'], sortWeight: 3, fallbackDelta: 0.3 },
    { statType: 'assists', label: 'Assists', aliases: ['assists', 'assist'], theOddsMarketKey: 'player_assists', sortWeight: 4, fallbackDelta: 0.3 },
  ],
  la_liga: [
    { statType: 'shots', label: 'Shots', aliases: ['shots', 'shot'], theOddsMarketKey: 'player_shots', sortWeight: 1, fallbackDelta: 0.8 },
    { statType: 'shots_onTarget', label: 'Shots on Target', aliases: ['shotsontarget', 'shots_on_target', 'shotontarget', 'sot'], theOddsMarketKey: 'player_shots_on_target', sortWeight: 2, fallbackDelta: 0.4 },
    { statType: 'goals', label: 'Goals', aliases: ['goals', 'goal'], sortWeight: 3, fallbackDelta: 0.3 },
    { statType: 'assists', label: 'Assists', aliases: ['assists', 'assist'], theOddsMarketKey: 'player_assists', sortWeight: 4, fallbackDelta: 0.3 },
  ],
  bundesliga: [
    { statType: 'shots', label: 'Shots', aliases: ['shots', 'shot'], theOddsMarketKey: 'player_shots', sortWeight: 1, fallbackDelta: 0.8 },
    { statType: 'shots_onTarget', label: 'Shots on Target', aliases: ['shotsontarget', 'shots_on_target', 'shotontarget', 'sot'], theOddsMarketKey: 'player_shots_on_target', sortWeight: 2, fallbackDelta: 0.4 },
    { statType: 'goals', label: 'Goals', aliases: ['goals', 'goal'], sortWeight: 3, fallbackDelta: 0.3 },
    { statType: 'assists', label: 'Assists', aliases: ['assists', 'assist'], theOddsMarketKey: 'player_assists', sortWeight: 4, fallbackDelta: 0.3 },
  ],
  serie_a: [
    { statType: 'shots', label: 'Shots', aliases: ['shots', 'shot'], theOddsMarketKey: 'player_shots', sortWeight: 1, fallbackDelta: 0.8 },
    { statType: 'shots_onTarget', label: 'Shots on Target', aliases: ['shotsontarget', 'shots_on_target', 'shotontarget', 'sot'], theOddsMarketKey: 'player_shots_on_target', sortWeight: 2, fallbackDelta: 0.4 },
    { statType: 'goals', label: 'Goals', aliases: ['goals', 'goal'], sortWeight: 3, fallbackDelta: 0.3 },
    { statType: 'assists', label: 'Assists', aliases: ['assists', 'assist'], theOddsMarketKey: 'player_assists', sortWeight: 4, fallbackDelta: 0.3 },
  ],
  ligue_1: [
    { statType: 'shots', label: 'Shots', aliases: ['shots', 'shot'], theOddsMarketKey: 'player_shots', sortWeight: 1, fallbackDelta: 0.8 },
    { statType: 'shots_onTarget', label: 'Shots on Target', aliases: ['shotsontarget', 'shots_on_target', 'shotontarget', 'sot'], theOddsMarketKey: 'player_shots_on_target', sortWeight: 2, fallbackDelta: 0.4 },
    { statType: 'goals', label: 'Goals', aliases: ['goals', 'goal'], sortWeight: 3, fallbackDelta: 0.3 },
    { statType: 'assists', label: 'Assists', aliases: ['assists', 'assist'], theOddsMarketKey: 'player_assists', sortWeight: 4, fallbackDelta: 0.3 },
  ],
  champions_league: [
    { statType: 'shots', label: 'Shots', aliases: ['shots', 'shot'], theOddsMarketKey: 'player_shots', sortWeight: 1, fallbackDelta: 0.8 },
    { statType: 'shots_onTarget', label: 'Shots on Target', aliases: ['shotsontarget', 'shots_on_target', 'shotontarget', 'sot'], theOddsMarketKey: 'player_shots_on_target', sortWeight: 2, fallbackDelta: 0.4 },
    { statType: 'goals', label: 'Goals', aliases: ['goals', 'goal'], sortWeight: 3, fallbackDelta: 0.3 },
    { statType: 'assists', label: 'Assists', aliases: ['assists', 'assist'], theOddsMarketKey: 'player_assists', sortWeight: 4, fallbackDelta: 0.3 },
  ],
};

function normalizeRegistryToken(value: string | null | undefined): string {
  return String(value || '')
    .normalize('NFD')
    .replace(/[\u0300-\u036f]/g, '')
    .toLowerCase()
    .replace(/[^a-z0-9]/g, '');
}

function getLeagueDefinitions(league: string | null | undefined): PlayerPropMarketDefinition[] {
  return PLAYER_PROP_MARKET_REGISTRY[String(league || '').trim().toLowerCase()] || [];
}

export function getRegisteredPlayerPropLeagues(): string[] {
  return Object.keys(PLAYER_PROP_MARKET_REGISTRY);
}

export function getPlayerPropMarketDefinitions(league: string | null | undefined): PlayerPropMarketDefinition[] {
  return getLeagueDefinitions(league);
}

export function getSupportedPlayerPropTypes(league: string | null | undefined): string[] {
  return getLeagueDefinitions(league).map((definition) => definition.statType);
}

export function getSupportedPlayerPropLabels(league: string | null | undefined): string[] {
  const labels: string[] = [];
  const seen = new Set<string>();

  for (const definition of getLeagueDefinitions(league)) {
    const key = normalizeRegistryToken(definition.label);
    if (!key || seen.has(key)) continue;
    seen.add(key);
    labels.push(definition.label);
  }

  return labels;
}

export function getSupportedPlayerPropQueryValues(league: string | null | undefined): string[] {
  const values: string[] = [];
  const seen = new Set<string>();

  for (const definition of getLeagueDefinitions(league)) {
    for (const value of [definition.statType, ...definition.aliases]) {
      const normalized = String(value || '').trim().toLowerCase();
      if (!normalized || seen.has(normalized)) continue;
      seen.add(normalized);
      values.push(normalized);
    }
  }

  return values;
}

export function getPlayerPropMarketDefinition(
  league: string | null | undefined,
  value: string | null | undefined,
): PlayerPropMarketDefinition | null {
  const token = normalizeRegistryToken(value);
  if (!token) return null;

  for (const definition of getLeagueDefinitions(league)) {
    if (normalizeRegistryToken(definition.statType) === token) return definition;
    if (definition.aliases.some((alias) => normalizeRegistryToken(alias) === token)) return definition;
  }

  return null;
}

export function normalizePlayerPropMarketStat(
  league: string | null | undefined,
  value: string | null | undefined,
): string | null {
  return getPlayerPropMarketDefinition(league, value)?.statType || null;
}

export function canonicalizePlayerPropStat(
  league: string | null | undefined,
  value: string | null | undefined,
): string | null {
  const trimmed = String(value || '').trim();
  if (!trimmed) return null;
  return normalizePlayerPropMarketStat(league, trimmed) || trimmed;
}

export function resolvePlayerPropStatIdentity(params: {
  league: string | null | undefined;
  statType?: string | null;
  normalizedStatType?: string | null;
  propText?: string | null;
}): { statType: string | null; normalizedStatType: string | null } {
  const canonical = canonicalizePlayerPropStat(
    params.league,
    params.normalizedStatType || params.statType || params.propText || null,
  );

  return {
    statType: canonical,
    normalizedStatType: canonical,
  };
}

export function buildPlayerPropIdentityKey(
  league: string | null | undefined,
  value: string | null | undefined,
): string {
  return String(canonicalizePlayerPropStat(league, value) || value || '')
    .trim()
    .toLowerCase()
    .replace(/[^a-z0-9]/g, '');
}

export function getPlayerPropLabelForLeague(
  league: string | null | undefined,
  value: string | null | undefined,
): string | null {
  return getPlayerPropMarketDefinition(league, value)?.label || null;
}

export function getPlayerPropSortWeightForLeague(
  league: string | null | undefined,
  value: string | null | undefined,
): number {
  return getPlayerPropMarketDefinition(league, value)?.sortWeight ?? 99;
}

export function getPlayerPropFallbackDeltaForLeague(
  league: string | null | undefined,
  value: string | null | undefined,
): number | null {
  return getPlayerPropMarketDefinition(league, value)?.fallbackDelta ?? null;
}

export function getTheOddsPlayerPropMarketKeyForLeague(
  league: string | null | undefined,
  value: string | null | undefined,
): string | null {
  return getPlayerPropMarketDefinition(league, value)?.theOddsMarketKey || null;
}

export const __playerPropMarketRegistry = PLAYER_PROP_MARKET_REGISTRY;
