import { createContext, useContext, useState, useEffect } from 'react'
import type { ReactNode } from 'react'

interface ServerInfo {
  name: string
  ip: string
  port: number
  category: 'Surf' | 'Kz' | 'Bhop'
}

interface A2SResponse {
  appID: number
  botCount: number
  environment: string
  gameDescription: string
  gameDirectory: string
  mapName: string
  maxPlayers: number
  playerCount: number
  serverName: string
  serverType: string
  vac: number
  version: string
  visibility: number
}

export interface ServerData extends ServerInfo {
  a2sData?: A2SResponse
  status: 'online' | 'offline' | 'loading'
  error?: string
}

interface ServerContextType {
  servers: ServerData[]
  loading: boolean
  lastUpdated: number
  hasInitialData: boolean
}

const ServerContext = createContext<ServerContextType | undefined>(undefined)

// Server list from database export
const serverList: ServerInfo[] = [
  { name: 'Surf 66 Tick #1', ip: '14.103.233.1', port: 27015, category: 'Surf' },
  { name: 'Surf 66 Tick #2', ip: '14.103.233.1', port: 27016, category: 'Surf' },
  { name: 'Surf 66 Tick #3', ip: '14.103.233.1', port: 27017, category: 'Surf' },
  { name: 'Surf 100 Tick #1', ip: '14.103.233.1', port: 28015, category: 'Surf' },
  { name: 'Surf 100 Tick #2', ip: '14.103.233.1', port: 28016, category: 'Surf' },
  { name: 'Kz #1', ip: '14.103.233.1', port: 29015, category: 'Kz' },
  { name: 'Kz #2', ip: '14.103.233.1', port: 29016, category: 'Kz' },
  { name: 'Bhop #1', ip: '14.103.233.1', port: 30015, category: 'Bhop' },
  { name: 'Bhop #2', ip: '14.103.233.1', port: 30016, category: 'Bhop' }
]

export function ServerProvider({ children }: { children: ReactNode }) {
  const [servers, setServers] = useState<ServerData[]>([])
  const [loading, setLoading] = useState(true)
  const [lastUpdated, setLastUpdated] = useState(Date.now())
  const [hasInitialData, setHasInitialData] = useState(false)

  const fetchServerData = async () => {
    try {
      // Batch query all servers in a single API call
      const response = await fetch('/api/server/statistics/a2s-query', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          servers: serverList.map(server => ({
            serverIP: server.ip,
            serverPort: server.port,
            timeout: 3000
          }))
        })
      })

      if (!response.ok) {
        throw new Error(`HTTP ${response.status}`)
      }

      const data = await response.json()
      
      // Update servers state with new data
      setServers(prevServers => {
        const results: ServerData[] = serverList.map((server, index) => {
          const a2sData = data.results?.[index]
          
          if (a2sData) {
            return {
              ...server,
              a2sData,
              status: 'online' as const
            }
          } else {
            // If no data for this server but we have previous data, keep the previous data
            const prevServer = prevServers.find(s => s.ip === server.ip && s.port === server.port)
            if (prevServer?.a2sData) {
              return prevServer // Keep previous successful data
            }
            return {
              ...server,
              status: 'offline' as const,
              error: 'No response from server'
            }
          }
        })
        return results
      })

      setLoading(false)
      setLastUpdated(Date.now())
      setHasInitialData(true)
    } catch (error) {
      console.error('Failed to fetch server data:', error)
      
      // If we already have data from a previous successful fetch, keep using it
      // Only show error state if this is the very first fetch attempt
      setServers(prevServers => {
        // Check if we have any previous successful data
        const hasPreviousData = prevServers.some(s => s.a2sData)
        
        if (hasPreviousData) {
          // Keep previous data on polling errors
          return prevServers
        } else {
          // First fetch failed, show offline state
          const offlineServers: ServerData[] = serverList.map(server => ({
            ...server,
            status: 'offline' as const,
            error: error instanceof Error ? error.message : 'Unknown error'
          }))
          return offlineServers
        }
      })
      
      setLoading(false)
      // Don't update lastUpdated on error to keep showing previous successful fetch time
    }
  }

  // Initial fetch and polling every 2 seconds
  useEffect(() => {
    fetchServerData()

    const interval = setInterval(() => {
      fetchServerData()
    }, 2000) // Poll every 2 seconds

    return () => clearInterval(interval)
  }, []) // Empty dependency array is intentional - we want this to run once

  return (
    <ServerContext.Provider value={{ servers, loading, lastUpdated, hasInitialData }}>
      {children}
    </ServerContext.Provider>
  )
}

export function useServers() {
  const context = useContext(ServerContext)
  if (context === undefined) {
    throw new Error('useServers must be used within a ServerProvider')
  }
  return context
}
