/**
 * MLB park factors (Session 15).
 *
 * Source: FanGraphs 2024-25 park factor data (three-year weighted
 * average — FanGraphs methodology). Numbers indexed to 100 = league
 * average. Pulled from https://www.fangraphs.com/guts.aspx (Park
 * Factors tab) 2025-04. Update annually; the rolling-three-year
 * window means values move slowly.
 *
 * Fields per park:
 *   hr — home run factor (Coors ~128 means HRs are 28% more likely;
 *        Oracle/SF ~85 means 15% less likely)
 *   h  — overall hit factor
 *   r  — runs factor
 *
 * The feature extractor reads this via `getParkFactor(homeTeam)`
 * during the MLB branch and merges hr/h/r as `park_hr`, `park_h`,
 * `park_r` so the grading engine + reasoning builder can read them
 * without re-doing the lookup.
 *
 * Indexing convention: home-team abbreviation. The road team plays
 * at the home team's park, so a Yankees-at-Angels game uses LAA's
 * park factors regardless of whose batter you're grading.
 */

const PARK_FACTORS = Object.freeze({
  // AL East
  BAL: { hr: 109, h: 100, r: 102 },  // Camden Yards — left field wall changes leveled off post-2022
  BOS: { hr: 100, h: 108, r: 106 },  // Fenway — Monster boosts singles/doubles, suppresses HR
  NYY: { hr: 114, h: 101, r: 104 },  // Yankee Stadium — short porch in right
  TB:  { hr:  93, h:  96, r:  94 },  // Tropicana — neutral-to-pitcher dome
  TOR: { hr: 106, h: 101, r: 102 },  // Rogers Centre — slight HR boost

  // AL Central
  CHW: { hr: 109, h: 102, r: 105 },  // Guaranteed Rate Field
  CLE: { hr:  96, h:  99, r:  98 },  // Progressive Field — slight pitcher park
  DET: { hr:  90, h: 100, r:  97 },  // Comerica — deep alleys, HR-suppressed
  KC:  { hr:  93, h: 103, r: 101 },  // Kauffman — XBH-friendly, HR-neutral
  MIN: { hr: 105, h: 100, r: 101 },  // Target Field

  // AL West
  HOU: { hr: 100, h: 101, r: 101 },  // Minute Maid — Crawford boxes ~neutral, dome
  LAA: { hr:  97, h:  98, r:  98 },  // Angel Stadium
  OAK: { hr:  91, h:  95, r:  92 },  // Coliseum — extreme pitcher park
  SEA: { hr:  96, h:  98, r:  96 },  // T-Mobile Park — marine air
  TEX: { hr: 104, h: 102, r: 103 },  // Globe Life — climate-controlled since 2020

  // NL East
  ATL: { hr: 103, h: 100, r: 101 },  // Truist Park
  MIA: { hr:  89, h:  97, r:  94 },  // loanDepot park — deep alleys
  NYM: { hr:  95, h:  99, r:  97 },  // Citi Field — slight pitcher
  PHI: { hr: 109, h: 100, r: 102 },  // Citizens Bank Park — bandbox right field
  WSH: { hr: 100, h: 100, r: 100 },  // Nationals Park — true neutral

  // NL Central
  CHC: { hr: 106, h: 100, r: 102 },  // Wrigley — wind-driven swings; multi-year average
  CIN: { hr: 113, h: 102, r: 105 },  // Great American — top-3 HR park most years
  MIL: { hr: 104, h: 100, r: 101 },  // American Family Field
  PIT: { hr:  96, h: 101, r:  99 },  // PNC Park — XBH-favorable, HR-suppressed
  STL: { hr:  93, h:  98, r:  96 },  // Busch — neutral-to-pitcher

  // NL West
  ARI: { hr: 100, h:  98, r:  98 },  // Chase Field — humidor since 2018
  COL: { hr: 128, h: 112, r: 120 },  // Coors Field — altitude. Single biggest park effect.
  LAD: { hr: 102, h:  99, r:  99 },  // Dodger Stadium
  SD:  { hr:  95, h:  97, r:  95 },  // Petco — marine air pitcher park
  SF:  { hr:  85, h:  96, r:  92 },  // Oracle Park — Bay winds suppress HRs heavily
});

const NEUTRAL = Object.freeze({ hr: 100, h: 100, r: 100 });

function normalizeTeamCode(team) {
  if (!team) return null;
  return String(team).trim().toUpperCase();
}

/**
 * getParkFactor — lookup by home-team code. Returns null for unknown
 * teams so the feature extractor can drop the signal entirely rather
 * than falsely report "neutral park" on a misspelled abbreviation.
 *
 * @param {string} homeTeam — three-letter team code (BAL, NYY, COL, ...)
 * @returns {{hr:number, h:number, r:number}|null}
 */
function getParkFactor(homeTeam) {
  const code = normalizeTeamCode(homeTeam);
  if (!code) return null;
  return PARK_FACTORS[code] || null;
}

/**
 * Convenience — when you want a guaranteed object (e.g. arithmetic
 * downstream that can't handle null). Falls back to league-neutral.
 * Prefer getParkFactor + explicit-null branching in code; this is
 * for tests and downstream services that prefer 100s over null.
 */
function getParkFactorOrNeutral(homeTeam) {
  return getParkFactor(homeTeam) || NEUTRAL;
}

module.exports = {
  PARK_FACTORS,
  NEUTRAL,
  getParkFactor,
  getParkFactorOrNeutral,
  __internals: { normalizeTeamCode },
};
