import { useEffect, useRef, useCallback } from 'react'
import { useQueryClient } from '@tanstack/react-query'
import { WS_URL } from '@/utils/constants'
import { useAuthStore } from '@/store'

export interface WebSocketMessage {
  type: 'bet_created' | 'bet_taken' | 'bet_cancelled' | 'event_updated' | 'new_comment'
  data: {
    event_id: number
    bet_id?: number
    [key: string]: unknown
  }
}

interface UseEventWebSocketOptions {
  eventId: number
  onBetCreated?: (data: WebSocketMessage['data']) => void
  onBetTaken?: (data: WebSocketMessage['data']) => void
  onBetCancelled?: (data: WebSocketMessage['data']) => void
  onNewComment?: (data: WebSocketMessage['data']) => void
}

export function useEventWebSocket({ eventId, onBetCreated, onBetTaken, onBetCancelled, onNewComment }: UseEventWebSocketOptions) {
  const wsRef = useRef<WebSocket | null>(null)
  const reconnectTimeoutRef = useRef<NodeJS.Timeout | null>(null)
  const queryClient = useQueryClient()
  const { token } = useAuthStore()

  // Use refs for callbacks to avoid reconnecting when they change
  const onBetCreatedRef = useRef(onBetCreated)
  const onBetTakenRef = useRef(onBetTaken)
  const onBetCancelledRef = useRef(onBetCancelled)
  const onNewCommentRef = useRef(onNewComment)

  // Update refs when callbacks change
  useEffect(() => {
    onBetCreatedRef.current = onBetCreated
    onBetTakenRef.current = onBetTaken
    onBetCancelledRef.current = onBetCancelled
    onNewCommentRef.current = onNewComment
  }, [onBetCreated, onBetTaken, onBetCancelled, onNewComment])

  const invalidateEventQueries = useCallback(() => {
    console.log('[WebSocket] Refetching queries for event', eventId)
    // Force refetch queries - use refetchQueries for immediate update
    queryClient.refetchQueries({
      predicate: (query) => {
        const key = query.queryKey
        const match = Array.isArray(key) && key[0] === 'sport-event' && key[1] === eventId
        if (match) console.log('[WebSocket] Refetching query:', key)
        return match
      },
    })
    queryClient.refetchQueries({ queryKey: ['my-active-bets'] })
  }, [queryClient, eventId])

  useEffect(() => {
    // Build WebSocket URL with token and event subscription
    const wsToken = token || 'guest'
    const wsUrl = `${WS_URL}/api/v1/ws?token=${wsToken}&event_id=${eventId}`

    const connect = () => {
      // Clean up existing connection
      if (wsRef.current && wsRef.current.readyState === WebSocket.OPEN) {
        return // Already connected
      }

      try {
        console.log(`[WebSocket] Connecting to ${wsUrl}`)
        const ws = new WebSocket(wsUrl)

        ws.onopen = () => {
          console.log(`[WebSocket] Connected to event ${eventId}`)
        }

        ws.onmessage = (event) => {
          try {
            const message: WebSocketMessage = JSON.parse(event.data)
            console.log('[WebSocket] Message received:', message)

            // Only process messages for this event
            if (message.data?.event_id !== eventId) return

            switch (message.type) {
              case 'bet_created':
                onBetCreatedRef.current?.(message.data)
                invalidateEventQueries()
                break
              case 'bet_taken':
                onBetTakenRef.current?.(message.data)
                invalidateEventQueries()
                break
              case 'bet_cancelled':
                onBetCancelledRef.current?.(message.data)
                invalidateEventQueries()
                break
              case 'event_updated':
                invalidateEventQueries()
                break
              case 'new_comment':
                onNewCommentRef.current?.(message.data)
                // Also refetch comments
                queryClient.invalidateQueries({ queryKey: ['event-comments', eventId] })
                break
            }
          } catch (err) {
            console.error('[WebSocket] Failed to parse message:', err)
          }
        }

        ws.onclose = (event) => {
          console.log(`[WebSocket] Disconnected from event ${eventId}`, event.code, event.reason)
          wsRef.current = null

          // Attempt to reconnect after 3 seconds (unless it was a normal closure)
          if (event.code !== 1000) {
            reconnectTimeoutRef.current = setTimeout(() => {
              console.log('[WebSocket] Attempting to reconnect...')
              connect()
            }, 3000)
          }
        }

        ws.onerror = (error) => {
          console.error('[WebSocket] Error:', error)
        }

        wsRef.current = ws
      } catch (err) {
        console.error('[WebSocket] Failed to connect:', err)
      }
    }

    connect()

    return () => {
      if (reconnectTimeoutRef.current) {
        clearTimeout(reconnectTimeoutRef.current)
      }
      if (wsRef.current) {
        wsRef.current.close(1000, 'Component unmounted')
        wsRef.current = null
      }
    }
  }, [eventId, token, invalidateEventQueries])

  return {
    isConnected: wsRef.current?.readyState === WebSocket.OPEN,
  }
}
