import type { Game, Team } from './apiResponseTypes'
import type { Player } from './playersService'
import { MODERN_STAT_ERA_START, SITE_URL, avg, obp, ops, slg, woba } from './utilities'

// TODO make a stats object that has properties for current regular season, current post season, 
// last 4 games, historical seasons, career totals
// could split into batting/pitching/fielding so only necessary ones are called to save time

export interface BattingStat {
  player: Player
  team: Team
  game: Game | 'TOT'
  // stats below
  pa: number
  ab: number
  run: number
  hit: number
  rbi: number
  double: number
  triple: number
  hr: number
  bb: number
  so: number
  hbp: number
  sac: number
  ibb: number
  gidp: number
  sb: number
  cs: number
  bphr: number
  bpfo: number
  bp1b: number
  bplo: number
  wpa: number
  avg: number
  obp: number
  slg: number
  ops: number
  woba: number
}

interface LegacyBattingStat {
  player: Player
  team: Team
  pa: number,
  ab: number,
  run: number,
  hit: number,
  rbi: number,
  double: number,
  triple: number,
  hr: number,
  bb: number,
  so: number,
  hbp: number,
  sac: number,
  ibb: number,
  gidp: number,
  sb: number,
  cs: number,
  bphr: number,
  bpfo: number,
  bp1b: number,
  bplo: number
}

export async function fetchBattingStatsBySeasonAndPlayerId(seasonNumber: number, playerId: number, isRegularSeason: boolean): Promise<BattingStat | undefined> {
  // different endpoint for pre-modern stats (/plays) era
  if (seasonNumber < MODERN_STAT_ERA_START) {
    return await fetchLegacyBattingStatsBySeasonAndPlayerId(seasonNumber, playerId, isRegularSeason)
  }

  const response = await fetch(`${SITE_URL}/api/v3/plays/batting?season=${seasonNumber}&player_id=${playerId}&s_type=${isRegularSeason ? 'regular' : 'post'}`)

  const battingStatsResponse: {
    count: number
    stats: BattingStat[]
  } = await response.json()

  if (battingStatsResponse.count === 0) return undefined

  if (battingStatsResponse.count > 1) {
    throw new Error('battingStatsService.fetchBattingStatsBySeasonAndPlayerId - Expected one stat line for season/player, return contained many')
  }

  return battingStatsResponse.stats[0]
}

async function fetchLegacyBattingStatsBySeasonAndPlayerId(seasonNumber: number, playerId: number, isRegularSeason: boolean): Promise<BattingStat | undefined> {
  const response = await fetch(`${SITE_URL}/api/v3/battingstats/totals?season=${seasonNumber}&player_id=${playerId}&s_type=${isRegularSeason ? 'regular' : 'post'}`)

  const legacyBattingStatsResponse: {
    count: number
    stats: LegacyBattingStat[]
  } = await response.json()

  if (legacyBattingStatsResponse.count === 0) return undefined

  if (legacyBattingStatsResponse.count > 1) {
    throw new Error('battingStatsService.fetchLegacyBattingStatsBySeasonAndPlayerId - Expected one stat line for season/player, return contained many')
  }

  return makeModernBattingStatFromLegacy(legacyBattingStatsResponse.stats[0])
}

export async function fetchBattingStatsForLastFourGamesBySeasonAndPlayerId(seasonNumber: number, playerId: number): Promise<BattingStat[]> {
  const response = await fetch(`${SITE_URL}/api/v3/plays/batting?season=${seasonNumber}&player_id=${playerId}&group_by=playergame&limit=4&s_type=regular&sort=newest`)

  const battingStatsResponse: {
    count: number
    stats: BattingStat[]
  } = await response.json()

  if (battingStatsResponse.count > 4) {
    throw new Error(`battingStatsService.fetchBattingStatsForLastFourBySeasonAndPlayerId - Expected at most 4 games, return contained ${battingStatsResponse.count}`)
  }

  return battingStatsResponse.stats
}

export function aggregateBattingStats(battingStats: BattingStat[]): BattingStat {
  let totalStat: BattingStat = {
    player: battingStats[0].player,
    team: battingStats[0].team,
    game: 'TOT',
    // stats below
    pa: 0,
    ab: 0,
    run: 0,
    hit: 0,
    rbi: 0,
    double: 0,
    triple: 0,
    hr: 0,
    bb: 0,
    so: 0,
    hbp: 0,
    sac: 0,
    ibb: 0,
    gidp: 0,
    sb: 0,
    cs: 0,
    bphr: 0,
    bpfo: 0,
    bp1b: 0,
    bplo: 0,
    wpa: 0,
    avg: 0,
    obp: 0,
    slg: 0,
    ops: 0,
    woba: 0
  }

  battingStats.forEach(stat => {
    totalStat.pa += stat.pa
    totalStat.ab += stat.ab
    totalStat.run += stat.run
    totalStat.hit += stat.hit
    totalStat.rbi += stat.rbi
    totalStat.double += stat.double
    totalStat.triple += stat.triple
    totalStat.hr += stat.hr
    totalStat.bb += stat.bb
    totalStat.so += stat.so
    totalStat.hbp += stat.hbp
    totalStat.sac += stat.sac
    totalStat.ibb += stat.ibb
    totalStat.gidp += stat.gidp
    totalStat.sb += stat.sb
    totalStat.cs += stat.cs
    totalStat.bphr += stat.bphr
    totalStat.bpfo += stat.bpfo
    totalStat.bp1b += stat.bp1b
    totalStat.bplo += stat.bplo
  })

  return {
    ...totalStat,
    avg: avg(totalStat),
    obp: obp(totalStat),
    slg: slg(totalStat),
    ops: ops(totalStat),
    woba: woba(totalStat)
  }
}

function makeModernBattingStatFromLegacy(legacyStat: LegacyBattingStat): BattingStat {
  return {
    player: legacyStat.player,
    team: legacyStat.team,
    game: 'TOT',
    // stats below
    pa: legacyStat.pa,
    ab: legacyStat.ab,
    run: legacyStat.run,
    hit: legacyStat.hit,
    rbi: legacyStat.rbi,
    double: legacyStat.double,
    triple: legacyStat.triple,
    hr: legacyStat.hr,
    bb: legacyStat.bb,
    so: legacyStat.so,
    hbp: legacyStat.hbp,
    sac: legacyStat.sac,
    ibb: legacyStat.ibb,
    gidp: legacyStat.gidp,
    sb: legacyStat.sb,
    cs: legacyStat.cs,
    bphr: legacyStat.bphr,
    bpfo: legacyStat.bpfo,
    bp1b: legacyStat.bp1b,
    bplo: legacyStat.bplo,
    wpa: 0,
    avg: avg(legacyStat),
    obp: obp(legacyStat),
    slg: slg(legacyStat),
    ops: ops(legacyStat),
    woba: woba(legacyStat)
  }
}
