// Game.tsx - Main game orchestrator (refactored from 3,315 lines to ~350 lines)
import { useState, useEffect } from 'react'
import { useTranslation } from 'react-i18next'
import api from '../services/api'
import { useGameEngine } from './game/hooks/useGameEngine'
import { Combat } from './game/Combat'
import LocationView from './game/LocationView'
import MovementControls from './game/MovementControls'
import PlayerSidebar from './game/PlayerSidebar'

import { GameProvider } from '../contexts/GameContext'
import { QuestJournal } from './game/QuestJournal'
import { CharacterSheet } from './game/CharacterSheet'
import GameHeader from './GameHeader'
import './Game.css'

function Game() {
  const { t, i18n } = useTranslation()

  const [token] = useState(() => localStorage.getItem('token'))
  const [showQuestJournal, setShowQuestJournal] = useState(false)
  const [showCharacterSheet, setShowCharacterSheet] = useState(false)

  // Handle WebSocket messages
  const handleWebSocketMessage = async (message: any) => {
    console.log('📨 WebSocket message:', message.type, message.data)

    switch (message.type) {
      case 'connected':
        console.log('✅ WebSocket connected! Server acknowledged connection.')
        break

      case 'location_update':
        // General location updates - update state directly from message data when possible
        console.log('🗺️ Location update:', message.data?.action, message.data?.message)

        let displayMessage = message.data?.message
        const action = message.data?.action

        // Handle translations for specific actions
        if (action === 'enemy_spawned' && message.data.npc_data) {
          const npcData = message.data.npc_data
          let npcName = npcData.name
          if (typeof npcName === 'object' && npcName !== null) {
            npcName = npcName[i18n.language] || npcName['en'] || npcName['es']
          }
          displayMessage = t('messages.enemyAppeared', { name: npcName })
        } else if (action === 'enemy_despawned') {
          displayMessage = t('messages.enemyDespawned')
        } else if (action === 'corpses_decayed' && message.data.count) {
          displayMessage = t('messages.corpsesDecayed', { count: message.data.count })
        } else if (action === 'items_decayed' && message.data.count) {
          displayMessage = t('messages.itemsDecayed', { count: message.data.count })
        }

        if (displayMessage) {
          actions.addLocationMessage(displayMessage)
        }
        if (action === 'player_arrived' && message.data.player_id) {
          // Add player to location directly without API call
          actions.addPlayerToLocation({
            id: message.data.player_id,
            name: message.data.player_name || message.data.username,
            level: message.data.player_level || 1,
            can_pvp: message.data.can_pvp || false
          })
        } else if (action === 'player_left' && message.data.player_id) {
          // Remove player from location directly without API call
          actions.removePlayerFromLocation(message.data.player_id)
        } else if (action === 'enemy_spawned' && message.data.npc_data) {
          // Add NPC directly without API call
          actions.addNPCToLocation(message.data.npc_data)
        } else if (action === 'enemy_despawned' && message.data.enemy_id) {
          // Remove NPC directly without API call
          actions.removeNPCFromLocation(message.data.enemy_id)
        } else {
          // For other actions (item_dropped, corpse_looted, etc), refresh location
          actions.refreshLocation()
        }
        break

      case 'state_update':
        // General state update - check what changed and update accordingly
        if (message.data?.player) {
          // Update player state directly if provided
          actions.updatePlayerState(message.data.player)
        }
        if (message.data?.location) {
          // Location changed - refresh location data
          actions.refreshLocation()
        }
        if (message.data?.encounter) {
          // Combat encounter - refresh combat state
          actions.refreshCombat()
        }
        break

      case 'combat_started':
        // New combat started - fetch combat state
        console.log('⚔️ Combat started', message.data)
        if (message.data?.pvp_combat) {
          // It's actually a PvP combat start
          actions.updateCombatState({
            is_pvp: true,
            in_combat: true,
            combat_over: false,
            pvp_combat: message.data.pvp_combat
          })
        } else {
          actions.refreshCombat()
        }
        break

      case 'combat_update':
        // Combat action occurred - update combat state directly if data provided
        console.log('⚔️ Combat update', message.data)
        if (message.data?.combat) {
          // PvE combat update
          actions.updateCombatState({
            ...message.data.combat,
            in_combat: true,
            combat_over: false
          })
        } else if (message.data?.pvp_combat) {
          // PvP combat update
          actions.updateCombatState({
            is_pvp: true,
            in_combat: true,
            combat_over: message.data.combat_over || false,
            pvp_combat: message.data.pvp_combat,
            messages: message.data.messages
          })
        }
        if (message.data?.player) {
          // Update player HP/XP/level from combat
          actions.updatePlayerState(message.data.player)
        }
        // Note: Don't refresh location here - combat_ended message will handle it
        break

      case 'combat_ended':
        // Combat finished - refresh location to see corpses/loot
        console.log('✅ Combat ended')
        actions.refreshLocation()
        actions.refreshCombat()
        break

      case 'pvp_started':
        // PvP combat started
        console.log('⚔️ PvP started', message.data)
        if (message.data?.pvp_combat) {
          // Initialize PvP combat state immediately
          actions.updateCombatState({
            is_pvp: true,
            in_combat: true,
            combat_over: false,
            pvp_combat: message.data.pvp_combat
          })
          // Skip fetching game data to avoid race condition with stale API state
        } else {
          actions.fetchGameData()
        }
        break

      case 'pvp_update':
        // PvP action occurred
        console.log('⚔️ PvP update', message.data)
        if (message.data?.pvp_combat) {
          // Update PvP combat state directly
          actions.updateCombatState({
            is_pvp: true,
            in_combat: true,
            combat_over: message.data.combat_over || false,
            pvp_combat: message.data.pvp_combat
          })
        } else {
          actions.fetchGameData()
        }
        break

      case 'item_picked_up':
        // Item looted - no location state change, just log message
        console.log('📦 Item picked up')
        if (message.data?.message) {
          actions.addLocationMessage(message.data.message)
        }
        // Don't refresh - no change to location items
        break

      case 'item_dropped':
        // Item dropped - refresh location to show new ground item
        console.log('📦 Item dropped')
        if (message.data?.message) {
          actions.addLocationMessage(message.data.message)
        }
        actions.refreshLocation()
        break

      case 'player_arrived':
        console.log('👤 Player arrived', message.data)
        if (message.data?.player_id) {
          actions.addPlayerToLocation({
            id: message.data.player_id,
            name: message.data.player_name || message.data.username,
            level: message.data.player_level || 1,
            can_pvp: message.data.can_pvp || false
          })
        }
        break

      case 'player_moved':
        // Not currently used - movement handled by location_update
        console.log('🚶 Player moved')
        actions.refreshLocation()
        break

      case 'interactable_cooldown':
        // Interactable used - update cooldown state directly
        console.log('⏳ Interactable cooldown')
        if (message.data?.instance_id && message.data?.action_id && message.data?.cooldown_remaining) {
          const cooldownKey = `${message.data.instance_id}:${message.data.action_id}`
          const cooldownExpiry = Date.now() / 1000 + message.data.cooldown_remaining
          actions.updateCooldowns({ [cooldownKey]: cooldownExpiry })
        }
        if (message.data?.message) {
          actions.addLocationMessage(message.data.message)
        }
        break

      case 'interactable_ready':
        // Interactable cooldown finished
        if (message.data?.action_name && message.data?.name) {
          actions.addLocationMessage(t('messages.interactableReady', {
            action: message.data.action_name,
            name: message.data.name
          }))
        } else if (message.data?.message) {
          actions.addLocationMessage(message.data.message)
        }
        break

      case 'status_effect_damage':
        if (message.data?.damage) {
          actions.addLocationMessage(t('messages.statusDamage', { damage: message.data.damage }))
          actions.updatePlayerState({ hp: message.data.hp })

          if (message.data.effects && Array.isArray(message.data.effects)) {
            message.data.effects.forEach((e: any) => {
              actions.updateStatusEffect(e.name, e.ticks_remaining)
            })
          } else if (message.data.name && message.data.ticks_remaining !== undefined) {
            actions.updateStatusEffect(message.data.name, message.data.ticks_remaining)
          }
        }
        break

      case 'status_effect_heal':
        if (message.data?.heal) {
          actions.addLocationMessage(t('messages.statusHeal', { heal: message.data.heal }))
          actions.updatePlayerState({ hp: message.data.hp })

          if (message.data.effects && Array.isArray(message.data.effects)) {
            message.data.effects.forEach((e: any) => {
              actions.updateStatusEffect(e.name, e.ticks_remaining)
            })
          } else if (message.data.name && message.data.ticks_remaining !== undefined) {
            actions.updateStatusEffect(message.data.name, message.data.ticks_remaining)
          }
        }
        break

      case 'player_died':
        if (message.data?.is_dead) {
          actions.addLocationMessage(t('messages.diedStatus'))
          actions.updatePlayerState({ hp: 0, is_dead: true })
        }
        break

      case 'stamina_update':
        if (message.data?.stamina) {
          // Only show message if significant change or if it's the regeneration event
          // actions.addLocationMessage(t('messages.staminaRegenerated')) 
          // (commented out to avoid spam, usually stamina update is silent or subtle)
          actions.updatePlayerState({ stamina: message.data.stamina })
        }
        break

      case 'player_count_update':
        // Handled by GameHeader, ignore here
        break

      case 'global_quest_completed':
        console.log('🌍 Global Quest Completed', message.data)
        actions.addLocationMessage(`🎉 GLOBAL QUEST COMPLETED: ${message.data.title}`)

        // Show unlocks if any
        if (message.data.outcome?.unlocks && message.data.outcome.unlocks.length > 0) {
          const unlocks = message.data.outcome.unlocks;
          // @ts-ignore
          const locationUnlocks = unlocks.filter((u: any) => u.type === 'location').map((u: any) => u.name).join(', ');
          // @ts-ignore
          const interactableUnlocks = unlocks.filter((u: any) => u.type === 'interactable').map((u: any) => u.name).join(', ');

          if (locationUnlocks) actions.addLocationMessage(`🔓 New Locations Unlocked: ${locationUnlocks}`);
          if (interactableUnlocks) actions.addLocationMessage(`🔓 New Content Unlocked: ${interactableUnlocks}`);
        }

        // Refresh everything to reflect unlocks and rewards
        actions.fetchGameData()
        break

      default:
        console.log('Unknown WebSocket message type:', message.type)
    }
  }

  // Initialize game engine
  const [state, actions] = useGameEngine(token, handleWebSocketMessage)

  // Redirect if not logged in
  useEffect(() => {
    if (!token) {
      window.location.href = '/login'
    }
  }, [token])

  // Loading state
  if (state.loading) {
    return (
      <div className="game-container loading">
        <div className="loading-spinner">⌛ Loading game...</div>
      </div>
    )
  }

  // Death overlay
  if (state.profile?.is_dead) {
    return (
      <div className="game-container death-overlay">
        <div className="death-screen">
          <h1>💀 You have died</h1>
          <p>Your adventure has come to an end.</p>
          <button onClick={() => {
            localStorage.removeItem('token')
            window.location.href = '/login'
          }}>
            Return to Login
          </button>
        </div>
      </div>
    )
  }



  // Create context value
  const gameContextValue = {
    token,
    locale: i18n.language,
    inventory: state.playerState?.inventory || [],
    state,
    actions
  }

  // No location loaded yet
  if (!state.location) {
    return (
      <div className="game-container loading">
        <div className="loading-spinner">⌛ Loading location...</div>
      </div>
    )
  }

  return (
    <GameProvider value={gameContextValue}>
      <GameHeader />
      <div className="game-container">
        {/* Quest Journal Toggle Button - Add to header or float? 
          Let's add it floating for now or in the top right.
       */}


        {/* Mobile Header Toggle - only show in main view */}
        {state.mobileMenuOpen === 'none' && (
          <button
            className="mobile-header-toggle"
            onClick={() => actions.setMobileHeaderOpen(!state.mobileHeaderOpen)}
          >
            {state.mobileHeaderOpen ? '✕' : '☰'}
          </button>
        )}

        {/* Main game area */}
        <div className="game-main">
          <div className="explore-tab-desktop">
            {/* Left Sidebar: Movement & Surroundings */}
            <div className={`left-sidebar mobile-menu-panel ${state.mobileMenuOpen === 'left' ? 'open' : ''}`}>
              {state.location && state.profile && (
                <MovementControls
                  location={state.location}
                  profile={state.profile}
                  combatState={state.combatState}
                  movementCooldown={state.movementCooldown}
                  interactableCooldowns={state.interactableCooldowns}
                  onMove={actions.handleMove}
                  onInteract={actions.handleInteract}
                />
              )}
            </div>

            {/* Center: Location view or Combat */}
            <div className="center-area">
              {/* Combat view (when in combat) */}
              {state.combatState && state.playerState && (
                <Combat
                  combatState={state.combatState}
                  combatLog={state.combatLog}
                  profile={state.profile}
                  playerState={state.playerState}
                  equipment={state.equipment}
                  locationImage={state.location?.image_url}
                  onCombatAction={actions.handleCombatAction}
                  onPvPAction={async (action: string) => {
                    try {
                      const response = await api.post('/api/game/pvp/action', { action })
                      actions.setMessage(response.data.message || 'Action performed!')
                      // We don't need to fetchGameData here because the websocket update will handle it?
                      // The user said: "The timer is also not updating correctly, it should grab the latest data from the websocket update or from the action call."
                      // So we should probably update state from response if possible, OR fetch.
                      // Let's return the data so Combat.tsx can use it for animations.
                      // And let's fetchGameData to be safe, but maybe skip if we trust the websocket?
                      // Let's keep fetchGameData for now as a fallback.
                      await actions.fetchGameData()
                      return response.data
                    } catch (error: any) {
                      actions.setMessage(error.response?.data?.detail || 'PvP action failed')
                      return null
                    }
                  }}
                  onExitCombat={() => {
                    actions.handleExitCombat()
                  }}
                  onExitPvPCombat={actions.handleExitPvPCombat}
                  addCombatLogEntry={actions.addCombatLogEntry}
                  updatePlayerState={actions.updatePlayerState}
                  updateCombatState={actions.updateCombatState}
                />
              )}

              {/* Location view (when not in combat) */}
              {!state.combatState && state.location && state.playerState && (
                <LocationView
                  key={state.location.id}
                  location={state.location}
                  playerState={state.playerState}
                  combatState={state.combatState || null}
                  message={state.message}
                  locationMessages={state.locationMessages}
                  expandedCorpse={state.expandedCorpse}
                  corpseDetails={state.corpseDetails}
                  mobileMenuOpen={state.mobileMenuOpen}
                  showCraftingMenu={state.showCraftingMenu}
                  showRepairMenu={state.showRepairMenu}
                  workbenchTab={state.workbenchTab}
                  craftableItems={state.craftableItems}
                  repairableItems={state.repairableItems}
                  uncraftableItems={state.uncraftableItems}
                  craftFilter={state.craftFilter}
                  repairFilter={state.repairFilter}
                  uncraftFilter={state.uncraftFilter}
                  craftCategoryFilter={state.craftCategoryFilter}
                  profile={state.profile}
                  onSetMessage={actions.setMessage}
                  onInitiateCombat={actions.handleInitiateCombat}
                  onInitiatePvP={async (playerId: number) => {
                    try {
                      const response = await api.post('/api/game/pvp/initiate', { target_player_id: playerId })
                      actions.setMessage(response.data.message || 'PvP combat initiated!')
                      await actions.fetchGameData()
                    } catch (error: any) {
                      actions.setMessage(error.response?.data?.detail || 'Failed to initiate PvP')
                    }
                  }}
                  onPickup={actions.handlePickup}
                  onLootCorpse={actions.handleLootCorpse}
                  onLootCorpseItem={actions.handleLootCorpseItem}
                  onSetExpandedCorpse={(corpseId: string | null) => {
                    if (corpseId === null) {
                      actions.handleCloseCorpseDetails()
                    } else {
                      actions.handleViewCorpseDetails(corpseId)
                    }
                  }}
                  onOpenCrafting={actions.handleOpenCrafting}
                  onOpenRepair={actions.handleOpenRepair}
                  onCloseCrafting={actions.handleCloseCrafting}
                  onSwitchWorkbenchTab={actions.handleSwitchWorkbenchTab}
                  onSetCraftFilter={actions.setCraftFilter}
                  onSetRepairFilter={actions.setRepairFilter}
                  onSetUncraftFilter={actions.setUncraftFilter}
                  onSetCraftCategoryFilter={actions.setCraftCategoryFilter}
                  onCraft={async (itemId: number) => await actions.handleCraft(itemId.toString())}
                  onRepair={(uniqueItemId: string, inventoryId: number) => actions.handleRepairFromMenu(Number(uniqueItemId), inventoryId)}
                  onUncraft={(uniqueItemId: string, inventoryId: number, quantity?: number) => actions.handleUncraft(Number(uniqueItemId), inventoryId, quantity)}
                  failedActionItemId={state.failedActionItemId}
                  quests={state.quests}
                />
              )}
            </div>

            {/* Right sidebar: Stats + Inventory */}
            {state.playerState && state.profile && (
              <PlayerSidebar
                playerState={state.playerState}
                profile={state.profile}
                equipment={state.equipment}
                inventoryFilter={state.inventoryFilter}
                inventoryCategoryFilter={state.inventoryCategoryFilter}
                mobileMenuOpen={state.mobileMenuOpen}
                onSetInventoryFilter={actions.setInventoryFilter}
                onSetInventoryCategoryFilter={actions.setInventoryCategoryFilter}
                onUseItem={async (itemId: number, _invId: number) => {
                  await actions.handleUseItem(itemId.toString())
                }}
                onEquipItem={actions.handleEquipItem}
                onUnequipItem={actions.handleUnequipItem}
                onDropItem={async (itemId: number, invId: number, quantity: number) => {
                  await actions.handleDropItem(itemId.toString(), quantity, invId)
                }}
                onSpendPoint={actions.handleSpendPoint}
                onOpenQuestJournal={() => setShowQuestJournal(true)}
                onOpenCharacterSheet={() => setShowCharacterSheet(true)}
              />
            )}
          </div>

          {/* Mobile Tab Navigation */}
          <div className="mobile-menu-buttons">
            <button
              className={`mobile-menu-btn left-btn ${state.mobileMenuOpen === 'left' ? 'active' : ''}`}
              onClick={() => actions.setMobileMenuOpen(state.mobileMenuOpen === 'left' ? 'none' : 'left')}
            >
              <span>🧭</span>
            </button>
            <button
              className={`mobile-menu-btn bottom-btn ${state.mobileMenuOpen === 'bottom' ? 'active' : ''}`}
              onClick={() => actions.setMobileMenuOpen(state.mobileMenuOpen === 'bottom' ? 'none' : 'bottom')}
              disabled={!!state.combatState}
            >
              <span>📍</span>
            </button>
            <button
              className={`mobile-menu-btn right-btn ${state.mobileMenuOpen === 'right' ? 'active' : ''}`}
              onClick={() => actions.setMobileMenuOpen(state.mobileMenuOpen === 'right' ? 'none' : 'right')}
            >
              <span>🎒</span>
            </button>
          </div>

          {/* Mobile Menu Overlays */}
          {state.mobileMenuOpen !== 'none' && (
            <div
              className="mobile-menu-overlay"
              onClick={() => actions.setMobileMenuOpen('none')}
            />
          )}
        </div>

        {/* Mobile navigation */}
        <div className="mobile-nav">
          <button
            className={`mobile-nav-btn ${state.mobileMenuOpen === 'left' ? 'active' : ''}`}
            onClick={() => actions.setMobileMenuOpen(state.mobileMenuOpen === 'left' ? 'none' : 'left')}
          >
            🗺️<br />Map
          </button>
          <button
            className={`mobile-nav-btn ${state.mobileMenuOpen === 'bottom' ? 'active' : ''}`}
            onClick={() => actions.setMobileMenuOpen(state.mobileMenuOpen === 'bottom' ? 'none' : 'bottom')}
          >
            📦<br />Items
          </button>
          <button
            className={`mobile-nav-btn ${state.mobileMenuOpen === 'right' ? 'active' : ''}`}
            onClick={() => actions.setMobileMenuOpen(state.mobileMenuOpen === 'right' ? 'none' : 'right')}
          >
            🎒<br />Inventory
          </button>
          {/* Mobile Quest Button */}
          <button
            className={`mobile-nav-btn ${showQuestJournal ? 'active' : ''}`}
            onClick={() => setShowQuestJournal(!showQuestJournal)}
          >
            📜<br />Quests
          </button>
        </div>

        {showQuestJournal && (
          <QuestJournal onClose={() => setShowQuestJournal(false)} />
        )}

        {showCharacterSheet && (
          <CharacterSheet
            onClose={() => setShowCharacterSheet(false)}
            onSpendPoint={actions.handleSpendPoint}
          />
        )}
      </div>
    </GameProvider>
  )
}

export default Game
