/**
 * Game Store
 *
 * Manages active game state, synchronized with backend via WebSocket.
 * This is the central state container for real-time gameplay.
 */

import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import type {
  GameState,
  PlayResult,
  DecisionPrompt,
  DefensiveDecision,
  OffensiveDecision,
  RollData,
  Lineup,
  BenchPlayer,
} from '~/types'

export const useGameStore = defineStore('game', () => {
  // ============================================================================
  // State
  // ============================================================================

  const gameState = ref<GameState | null>(null)
  const homeLineup = ref<Lineup[]>([])
  const awayLineup = ref<Lineup[]>([])
  const homeBench = ref<BenchPlayer[]>([])
  const awayBench = ref<BenchPlayer[]>([])
  const playHistory = ref<PlayResult[]>([])
  const currentDecisionPrompt = ref<DecisionPrompt | null>(null)
  const pendingRoll = ref<RollData | null>(null)
  const lastPlayResult = ref<PlayResult | null>(null)
  const isConnected = ref(false)
  const isLoading = ref(false)
  const error = ref<string | null>(null)

  // Decision state (local pending decisions before submission)
  const pendingDefensiveSetup = ref<DefensiveDecision | null>(null)
  const pendingOffensiveDecision = ref<Omit<OffensiveDecision, 'steal_attempts'> | null>(null)
  const pendingStealAttempts = ref<number[]>([])
  const decisionHistory = ref<Array<{
    type: 'Defensive' | 'Offensive'
    summary: string
    timestamp: string
  }>>([])

  // ============================================================================
  // Getters
  // ============================================================================

  const gameId = computed(() => gameState.value?.game_id ?? null)
  const leagueId = computed(() => gameState.value?.league_id ?? null)
  const currentInning = computed(() => gameState.value?.inning ?? 1)
  const currentHalf = computed(() => gameState.value?.half ?? 'top')
  const outs = computed(() => gameState.value?.outs ?? 0)
  const balls = computed(() => gameState.value?.balls ?? 0)
  const strikes = computed(() => gameState.value?.strikes ?? 0)
  const homeScore = computed(() => gameState.value?.home_score ?? 0)
  const awayScore = computed(() => gameState.value?.away_score ?? 0)
  const gameStatus = computed(() => gameState.value?.status ?? 'pending')

  const isGameActive = computed(() => gameStatus.value === 'active')
  const isGameComplete = computed(() => gameStatus.value === 'completed')

  const currentBatter = computed(() => gameState.value?.current_batter ?? null)
  const currentPitcher = computed(() => gameState.value?.current_pitcher ?? null)
  const currentCatcher = computed(() => gameState.value?.current_catcher ?? null)

  const runnersOnBase = computed(() => {
    const runners: number[] = []
    if (gameState.value?.on_first) runners.push(1)
    if (gameState.value?.on_second) runners.push(2)
    if (gameState.value?.on_third) runners.push(3)
    return runners
  })

  const basesLoaded = computed(() => runnersOnBase.value.length === 3)
  const basesEmpty = computed(() => runnersOnBase.value.length === 0)
  const runnerInScoringPosition = computed(() =>
    runnersOnBase.value.includes(2) || runnersOnBase.value.includes(3)
  )

  const battingTeamId = computed(() => {
    if (!gameState.value) return null
    return gameState.value.half === 'top'
      ? gameState.value.away_team_id
      : gameState.value.home_team_id
  })

  const fieldingTeamId = computed(() => {
    if (!gameState.value) return null
    return gameState.value.half === 'top'
      ? gameState.value.home_team_id
      : gameState.value.away_team_id
  })

  const isBattingTeamAI = computed(() => {
    if (!gameState.value) return false
    return gameState.value.half === 'top'
      ? gameState.value.away_team_is_ai
      : gameState.value.home_team_is_ai
  })

  const isFieldingTeamAI = computed(() => {
    if (!gameState.value) return false
    return gameState.value.half === 'top'
      ? gameState.value.home_team_is_ai
      : gameState.value.away_team_is_ai
  })

  const needsDefensiveDecision = computed(() => {
    // Standardized naming (2025-01-21): Both backend and frontend now use 'awaiting_defensive'
    return currentDecisionPrompt.value?.phase === 'awaiting_defensive' ||
           gameState.value?.decision_phase === 'awaiting_defensive'
  })

  const needsOffensiveDecision = computed(() => {
    // Standardized naming (2025-01-21): Both backend and frontend now use 'awaiting_offensive'
    return currentDecisionPrompt.value?.phase === 'awaiting_offensive' ||
           gameState.value?.decision_phase === 'awaiting_offensive'
  })

  const needsStolenBaseDecision = computed(() => {
    // Standardized naming (2025-01-21): Both backend and frontend now use 'awaiting_stolen_base'
    return currentDecisionPrompt.value?.phase === 'awaiting_stolen_base' ||
           gameState.value?.decision_phase === 'awaiting_stolen_base'
  })

  const canRollDice = computed(() => {
    return gameState.value?.decision_phase === 'resolution' && !pendingRoll.value
  })

  const canSubmitOutcome = computed(() => {
    return pendingRoll.value !== null
  })

  const recentPlays = computed(() => {
    return playHistory.value.slice(-10).reverse()
  })

  // ============================================================================
  // Actions
  // ============================================================================

  /**
   * Set complete game state (from server)
   */
  function setGameState(state: GameState) {
    const oldBatter = gameState.value?.current_batter
    const newBatter = state?.current_batter
    const oldBatterInfo = oldBatter
      ? `lineup_id=${oldBatter.lineup_id}, batting_order=${oldBatter.batting_order}`
      : 'None'
    const newBatterInfo = newBatter
      ? `lineup_id=${newBatter.lineup_id}, batting_order=${newBatter.batting_order}`
      : 'None'
    console.log('[GameStore] setGameState - current_batter:', oldBatterInfo, '->', newBatterInfo)
    gameState.value = state
    error.value = null
  }

  /**
   * Update partial game state
   */
  function updateGameState(updates: Partial<GameState>) {
    if (gameState.value) {
      gameState.value = { ...gameState.value, ...updates }
    }
  }

  /**
   * Set lineups for both teams
   */
  function setLineups(home: Lineup[], away: Lineup[]) {
    homeLineup.value = home
    awayLineup.value = away
  }

  /**
   * Update lineup for a specific team
   */
  function updateLineup(teamId: number, lineup: Lineup[]) {
    if (teamId === gameState.value?.home_team_id) {
      homeLineup.value = lineup
    } else if (teamId === gameState.value?.away_team_id) {
      awayLineup.value = lineup
    }
  }

  /**
   * Set bench players for a specific team
   * Bench players come from RosterLink (players not in active lineup)
   * with is_pitcher/is_batter computed properties for UI filtering
   */
  function setBench(teamId: number, bench: BenchPlayer[]) {
    if (teamId === gameState.value?.home_team_id) {
      homeBench.value = bench
    } else if (teamId === gameState.value?.away_team_id) {
      awayBench.value = bench
    }
  }

  /**
   * Set play history (replaces entire array - used for initial sync)
   * O(1) operation - no deduplication needed
   */
  function setPlayHistory(plays: PlayResult[]) {
    playHistory.value = plays
  }

  /**
   * Add play to history (used for live play_resolved events)
   * O(1) operation - assumes no duplicates from live events
   */
  function addPlayToHistory(play: PlayResult) {
    playHistory.value.push(play)

    // Update game state from play result if provided
    if (play.new_state) {
      updateGameState(play.new_state)
    }
  }

  /**
   * Set current decision prompt
   */
  function setDecisionPrompt(prompt: DecisionPrompt | null) {
    currentDecisionPrompt.value = prompt
  }

  /**
   * Clear decision prompt after submission
   */
  function clearDecisionPrompt() {
    currentDecisionPrompt.value = null
  }

  /**
   * Set pending dice roll
   */
  function setPendingRoll(roll: RollData | null) {
    pendingRoll.value = roll
  }

  /**
   * Clear pending roll after outcome submission
   */
  function clearPendingRoll() {
    pendingRoll.value = null
  }

  /**
   * Set last play result
   */
  function setLastPlayResult(result: PlayResult | null) {
    lastPlayResult.value = result
  }

  /**
   * Clear last play result
   */
  function clearLastPlayResult() {
    lastPlayResult.value = null
  }

  /**
   * Set connection status
   */
  function setConnected(connected: boolean) {
    isConnected.value = connected
  }

  /**
   * Set loading state
   */
  function setLoading(loading: boolean) {
    isLoading.value = loading
  }

  /**
   * Set error
   */
  function setError(message: string | null) {
    error.value = message
  }

  /**
   * Set pending defensive setup (before submission)
   */
  function setPendingDefensiveSetup(setup: DefensiveDecision | null) {
    pendingDefensiveSetup.value = setup
  }

  /**
   * Set pending offensive decision (before submission)
   */
  function setPendingOffensiveDecision(decision: Omit<OffensiveDecision, 'steal_attempts'> | null) {
    pendingOffensiveDecision.value = decision
  }

  /**
   * Set pending steal attempts (before submission)
   */
  function setPendingStealAttempts(attempts: number[]) {
    pendingStealAttempts.value = attempts
  }

  /**
   * Add decision to history
   */
  function addDecisionToHistory(type: 'Defensive' | 'Offensive', summary: string) {
    decisionHistory.value.unshift({
      type,
      summary,
      timestamp: new Date().toLocaleTimeString(),
    })

    // Keep only last 10 decisions
    if (decisionHistory.value.length > 10) {
      decisionHistory.value = decisionHistory.value.slice(0, 10)
    }
  }

  /**
   * Clear all pending decisions
   */
  function clearPendingDecisions() {
    pendingDefensiveSetup.value = null
    pendingOffensiveDecision.value = null
    pendingStealAttempts.value = []
  }

  /**
   * Reset game store (when leaving game)
   */
  function resetGame() {
    gameState.value = null
    homeLineup.value = []
    awayLineup.value = []
    homeBench.value = []
    awayBench.value = []
    playHistory.value = []
    currentDecisionPrompt.value = null
    pendingRoll.value = null
    isConnected.value = false
    isLoading.value = false
    error.value = null
    pendingDefensiveSetup.value = null
    pendingOffensiveDecision.value = null
    pendingStealAttempts.value = []
    decisionHistory.value = []
  }

  /**
   * Get active lineup for a team
   */
  function getActiveLineup(teamId: number): Lineup[] {
    const lineup = teamId === gameState.value?.home_team_id
      ? homeLineup.value
      : awayLineup.value
    return lineup.filter(p => p.is_active)
  }

  /**
   * Get bench players for a team
   */
  function getBenchPlayers(teamId: number): Lineup[] {
    const lineup = teamId === gameState.value?.home_team_id
      ? homeLineup.value
      : awayLineup.value
    return lineup.filter(p => !p.is_active)
  }

  /**
   * Find player in lineup by lineup_id
   */
  function findPlayerInLineup(lineupId: number): Lineup | undefined {
    return [...homeLineup.value, ...awayLineup.value].find(
      p => p.lineup_id === lineupId
    )
  }

  // ============================================================================
  // Return Store API
  // ============================================================================

  return {
    // State
    gameState: readonly(gameState),
    homeLineup: readonly(homeLineup),
    awayLineup: readonly(awayLineup),
    homeBench: readonly(homeBench),
    awayBench: readonly(awayBench),
    playHistory: readonly(playHistory),
    currentDecisionPrompt: readonly(currentDecisionPrompt),
    pendingRoll: readonly(pendingRoll),
    lastPlayResult: readonly(lastPlayResult),
    isConnected: readonly(isConnected),
    isLoading: readonly(isLoading),
    error: readonly(error),
    pendingDefensiveSetup: readonly(pendingDefensiveSetup),
    pendingOffensiveDecision: readonly(pendingOffensiveDecision),
    pendingStealAttempts: readonly(pendingStealAttempts),
    decisionHistory: readonly(decisionHistory),

    // Getters
    gameId,
    leagueId,
    currentInning,
    currentHalf,
    outs,
    balls,
    strikes,
    homeScore,
    awayScore,
    gameStatus,
    isGameActive,
    isGameComplete,
    currentBatter,
    currentPitcher,
    currentCatcher,
    runnersOnBase,
    basesLoaded,
    basesEmpty,
    runnerInScoringPosition,
    battingTeamId,
    fieldingTeamId,
    isBattingTeamAI,
    isFieldingTeamAI,
    needsDefensiveDecision,
    needsOffensiveDecision,
    needsStolenBaseDecision,
    canRollDice,
    canSubmitOutcome,
    recentPlays,

    // Actions
    setGameState,
    updateGameState,
    setLineups,
    updateLineup,
    setBench,
    setPlayHistory,
    addPlayToHistory,
    setDecisionPrompt,
    clearDecisionPrompt,
    setPendingRoll,
    clearPendingRoll,
    setLastPlayResult,
    clearLastPlayResult,
    setConnected,
    setLoading,
    setError,
    setPendingDefensiveSetup,
    setPendingOffensiveDecision,
    setPendingStealAttempts,
    addDecisionToHistory,
    clearPendingDecisions,
    resetGame,
    getActiveLineup,
    getBenchPlayers,
    findPlayerInLineup,
  }
})
