import { useEffect, useRef, useState, useCallback } from 'react'
import { useAuthStore } from '../stores/auth'

const WS_URL = (import.meta as any).env?.VITE_WS_URL || 'ws://localhost:8000/ws'

interface WebSocketMessage {
  type: string
  channel?: string
  timestamp?: string
  data?: Record<string, unknown>
  payload?: Record<string, unknown>
}

interface UseWebSocketOptions {
  autoConnect?: boolean
  autoSubscribe?: string[]
  heartbeatInterval?: number
  onMessage?: (message: WebSocketMessage) => void
  onConnect?: () => void
  onDisconnect?: () => void
  onError?: (error: Error) => void
}

interface UseWebSocketReturn {
  connected: boolean
  lastMessage: WebSocketMessage | null
  sendMessage: (message: Record<string, unknown>) => void
  subscribe: (channels: string[]) => void
  connect: () => void
  disconnect: () => void
}

export function useWebSocket(options: UseWebSocketOptions = {}): UseWebSocketReturn {
  const {
    autoConnect = true,
    autoSubscribe = [],
    onMessage,
    onConnect,
    onDisconnect,
    onError,
  } = options

  const { token } = useAuthStore()
  console.log('[WebSocket] Token present:', !!token, token ? token.substring(0, 20) + '...' : 'none')
  console.log('[WebSocket] autoConnect:', autoConnect)

  const wsRef = useRef<WebSocket | null>(null)
  const [connected, setConnected] = useState(false)
  const [lastMessage, setLastMessage] = useState<WebSocketMessage | null>(null)
  const reconnectTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null)
  const heartbeatTimerRef = useRef<ReturnType<typeof setInterval> | null>(null)

  const connect = useCallback(() => {
    if (!token) {
      console.log('[WebSocket] No token, skipping connect')
      return
    }

    const wsUrl = `${WS_URL}?token=${token}`
    console.log('[WebSocket] Connecting to:', wsUrl)
    const ws = new WebSocket(wsUrl)

    ws.onopen = () => {
      console.log('[WebSocket] Connected!')
      setConnected(true)
      if (autoSubscribe.length > 0) {
        ws.send(JSON.stringify({ type: 'subscribe', data: { channels: autoSubscribe } }))
      }
      onConnect?.()
    }

    ws.onmessage = (event) => {
      console.log('[WebSocket] Received:', event.data)
      try {
        const message: WebSocketMessage = JSON.parse(event.data)
        setLastMessage(message)
        onMessage?.(message)
      } catch {
        console.error('Failed to parse WebSocket message')
      }
    }

    ws.onclose = (event) => {
      console.log('[WebSocket] Disconnected:', event.code, event.reason)
      setConnected(false)
      if (heartbeatTimerRef.current) {
        clearInterval(heartbeatTimerRef.current)
        heartbeatTimerRef.current = null
      }
      onDisconnect?.()

      if (autoConnect && token) {
        reconnectTimeoutRef.current = setTimeout(() => {
          console.log('[WebSocket] Reconnecting...')
          connect()
        }, 3000)
      }
    }

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

    wsRef.current = ws
  }, [token, autoConnect, autoSubscribe, onConnect, onDisconnect, onError])

  const disconnect = useCallback(() => {
    if (reconnectTimeoutRef.current) {
      clearTimeout(reconnectTimeoutRef.current)
      reconnectTimeoutRef.current = null
    }
    if (heartbeatTimerRef.current) {
      clearInterval(heartbeatTimerRef.current)
      heartbeatTimerRef.current = null
    }
    wsRef.current?.close()
    wsRef.current = null
    setConnected(false)
  }, [])

  const sendMessage = useCallback((message: Record<string, unknown>) => {
    wsRef.current?.send(JSON.stringify(message))
  }, [])

  const subscribe = useCallback((channels: string[]) => {
    wsRef.current?.send(JSON.stringify({
      type: 'subscribe',
      data: { channels }
    }))
  }, [])

  useEffect(() => {
    console.log('[WebSocket] useEffect triggered, autoConnect:', autoConnect, 'token:', !!token)
    if (autoConnect && token) {
      connect()
    }
    return () => {
      disconnect()
    }
  }, [autoConnect, token, connect, disconnect])

  return {
    connected,
    lastMessage,
    sendMessage,
    subscribe,
    connect,
    disconnect,
  }
}
