/**
 * WebSocket服务 - 替代MQTT直接连接
 * 通过WebSocket订阅机器人实时数据（位姿、轨迹、任务状态等）
 * 后端通过STOMP协议推送MQTT接收到的机器人数据
 */
import { ElNotification, ElMessage } from 'element-plus'
import SockJS from 'sockjs-client'
import Stomp from 'stompjs'

// 创建STOMP客户端
let stompClient = null
let socket = null
let isConnected = false
let reconnectTimer = null
let reconnectAttempts = 0
const MAX_RECONNECT_ATTEMPTS = 10
const RECONNECT_INTERVAL = 5000

// 订阅回调函数存储
const subscriptions = {}

// WebSocket连接配置
let wsConfig = {
  baseUrl: '',  // 会被设置为 {wsBase}/ws/robot
  deviceId: 'ld000001',
  onConnect: null,
  onDisconnect: null,
  onMessage: null,
  onError: null
}

/**
 * 初始化WebSocket连接
 * @param {Object} config 配置对象
 * @param {string} config.baseUrl WebSocket基础URL
 * @param {string} config.deviceId 设备ID
 * @param {Function} config.onConnect 连接成功回调
 * @param {Function} config.onDisconnect 断开连接回调
 * @param {Function} config.onMessage 消息接收回调
 * @param {Function} config.onError 错误回调
 */
export function initWebSocket(config) {
  console.log('[WebSocket] initWebSocket 被调用，传入参数:', config)
  console.log('[WebSocket] 当前 wsConfig:', JSON.parse(JSON.stringify(wsConfig)))
  
  // 合并配置：如果 config 中没有 deviceId，则保留 wsConfig 的默认值
  const mergedConfig = { ...wsConfig }
  if (config) {
    Object.keys(config).forEach(key => {
      if (config[key] !== undefined && config[key] !== null) {
        mergedConfig[key] = config[key]
      }
    })
  }
  wsConfig = mergedConfig
  
  console.log('[WebSocket] 合并后 wsConfig:', JSON.parse(JSON.stringify(wsConfig)))
  
  connect()
}

/**
 * 建立WebSocket连接
 */
function connect() {
  try {
    // 获取WebSocket URL
    // 如果配置了baseUrl，直接使用；否则从当前域名推断
    let wsUrl = wsConfig.baseUrl
    if (!wsUrl) {
      const protocol = window.location.protocol === 'https:' ? 'https:' : 'http:'
      const host = window.location.host
      wsUrl = `${protocol}//${host}`
    }
    
    const socketUrl = `${wsUrl}/ws/robot`
    
    console.log('[WebSocket] ===== WebSocket连接调试 =====')
    console.log('[WebSocket] 当前页面:', window.location.href)
    console.log('[WebSocket] 协议:', window.location.protocol)
    console.log('[WebSocket] 主机:', window.location.host)
    console.log('[WebSocket] 目标URL:', socketUrl)
    console.log('[WebSocket] 设备ID:', wsConfig.deviceId)
    console.log('[WebSocket] ==============================')
    
    // 创建SockJS连接
    socket = new SockJS(socketUrl)
    
    // 创建STOMP客户端
    stompClient = Stomp.over(socket)
    
    // 配置STOMP参数
    stompClient.connectHeaders = {}
    
    // 添加连接超时检测
    const connectionTimeout = setTimeout(() => {
      console.error('[WebSocket] 连接超时（10秒），可能连接失败')
    }, 10000)
    stompClient.debug = function(str) {
      if (str.includes('CONNECTED')) {
        console.log('[WebSocket] ✅ STOMP连接成功')
      } else if (str.includes('ERROR')) {
        console.error('[WebSocket] ❌ STOMP错误:', str)
      } else {
        console.log('[WebSocket]', str)
      }
    }
    
    // 连接成功回调
    stompClient.connect({}, 
      function(frame) {
        clearTimeout(connectionTimeout)
        isConnected = true
        reconnectAttempts = 0
        console.log('[WebSocket] 已连接:', frame)
        
        // 触发连接成功回调
        if (wsConfig.onConnect) {
          wsConfig.onConnect()
        }
        
        // 自动订阅设备专属频道
        if (wsConfig.deviceId) {
          subscribeToDevice(wsConfig.deviceId)
        }
        
        ElNotification({
          title: 'WebSocket连接成功',
          message: '已连接到机器人实时数据服务',
          type: 'success',
          duration: 3000
        })
      },
      function(error) {
        console.error('[WebSocket] 连接错误:', error)
        console.error('[WebSocket] 错误类型:', typeof error)
        console.error('[WebSocket] 错误详情:', JSON.stringify(error))
        isConnected = false
        
        if (wsConfig.onError) {
          wsConfig.onError(error)
        }
        
        // 触发断开连接回调
        if (wsConfig.onDisconnect) {
          wsConfig.onDisconnect()
        }
        
        // 自动重连
        handleReconnect()
      }
    )
  } catch (error) {
    console.error('[WebSocket] 连接异常:', error)
    handleReconnect()
  }
}

/**
 * 处理自动重连
 */
function handleReconnect() {
  if (reconnectAttempts >= MAX_RECONNECT_ATTEMPTS) {
    console.error('[WebSocket] 达到最大重连次数，停止重连')
    ElMessage.error('WebSocket连接失败，请刷新页面或检查网络')
    return
  }
  
  reconnectAttempts++
  console.log(`[WebSocket] ${RECONNECT_INTERVAL/1000}秒后尝试第${reconnectAttempts}次重连...`)
  
  if (reconnectTimer) {
    clearTimeout(reconnectTimer)
  }
  
  reconnectTimer = setTimeout(() => {
    console.log(`[WebSocket] 正在进行第${reconnectAttempts}次重连...`)
    connect()
  }, RECONNECT_INTERVAL)
}

/**
 * 订阅设备专属频道
 * @param {string} deviceId 设备ID
 */
export function subscribeToDevice(deviceId) {
  if (!stompClient || !isConnected) {
    console.warn('[WebSocket] 未连接，无法订阅')
    return
  }
  
  wsConfig.deviceId = deviceId
  
  // 取消之前的订阅
  unsubscribeAll()
  
  const prefix = `/topic/robot/${deviceId}`
  
  // 订阅位姿数据
  subscribe(`${prefix}/pose`, (message) => {
    if (wsConfig.onMessage) {
      wsConfig.onMessage('pose', message)
    }
  })
  
  // 订阅任务实时信息
  subscribe(`${prefix}/task`, (message) => {
    if (wsConfig.onMessage) {
      wsConfig.onMessage('task', message)
    }
  })
  
  // 订阅轨迹数据
  subscribe(`${prefix}/trajectory`, (message) => {
    if (wsConfig.onMessage) {
      wsConfig.onMessage('trajectory', message)
    }
  })
  
  // 订阅到达事件
  subscribe(`${prefix}/event`, (message) => {
    if (wsConfig.onMessage) {
      wsConfig.onMessage('arrive', message)
    }
  })
  
  // 订阅地图数据
  subscribe(`${prefix}/map`, (message) => {
    if (wsConfig.onMessage) {
      wsConfig.onMessage('map', message)
    }
  })
  
  // 订阅导航响应
  subscribe(`${prefix}/navigation`, (message) => {
    if (wsConfig.onMessage) {
      wsConfig.onMessage('navigation', message)
    }
  })
  
  // 订阅规划响应
  subscribe(`${prefix}/planning`, (message) => {
    if (wsConfig.onMessage) {
      wsConfig.onMessage('planning', message)
    }
  })
  
  // 订阅原始MQTT消息（用于调试）
  subscribe(`${prefix}/raw`, (message) => {
    if (wsConfig.onMessage) {
      wsConfig.onMessage('raw', message)
    }
  })
  
  // 订阅ASM功能状态（用于录制/构建/SLAM）
  subscribe(`${prefix}/asm`, (message) => {
    if (wsConfig.onMessage) {
      wsConfig.onMessage('asm', message)
    }
  })
  
  console.log(`[WebSocket] 已订阅设备 ${deviceId} 的所有频道`)
}

/**
 * 订阅指定频道
 * @param {string} channel 频道路径
 * @param {Function} callback 回调函数
 */
export function subscribe(channel, callback) {
  if (!stompClient || !isConnected) {
    console.warn(`[WebSocket] 未连接，无法订阅频道: ${channel}`)
    return
  }
  
  const subscription = stompClient.subscribe(channel, (message) => {
    try {
      const body = JSON.parse(message.body)
      callback(body)
    } catch (e) {
      console.error(`[WebSocket] 解析消息失败:`, e, message.body)
    }
  })
  
  subscriptions[channel] = subscription
  console.log(`[WebSocket] 已订阅频道: ${channel}`)
  
  return subscription
}

/**
 * 取消订阅指定频道
 * @param {string} channel 频道路径
 */
export function unsubscribe(channel) {
  if (subscriptions[channel]) {
    subscriptions[channel].unsubscribe()
    delete subscriptions[channel]
    console.log(`[WebSocket] 已取消订阅: ${channel}`)
  }
}

/**
 * 取消所有订阅
 */
export function unsubscribeAll() {
  Object.keys(subscriptions).forEach(channel => {
    if (subscriptions[channel]) {
      subscriptions[channel].unsubscribe()
    }
  })
  Object.keys(subscriptions).forEach(key => delete subscriptions[key])
  console.log('[WebSocket] 已取消所有订阅')
}

/**
 * 断开WebSocket连接
 */
export function disconnect() {
  if (reconnectTimer) {
    clearTimeout(reconnectTimer)
    reconnectTimer = null
  }
  
  unsubscribeAll()
  
  if (stompClient) {
    stompClient.disconnect(() => {
      console.log('[WebSocket] 已断开连接')
    })
    stompClient = null
  }
  
  if (socket) {
    socket.close()
    socket = null
  }
  
  isConnected = false
  // 重置配置时保留 deviceId 的默认值
  wsConfig = {
    baseUrl: '',
    deviceId: 'ld000001',  // 保持默认值，不重置为空
    onConnect: null,
    onDisconnect: null,
    onMessage: null,
    onError: null
  }
}

/**
 * 发送STOMP消息
 * @param {string} destination 目标路径
 * @param {Object} data 发送的数据
 */
export function sendMessage(destination, data) {
  if (!stompClient || !isConnected) {
    console.warn('[WebSocket] 未连接，无法发送消息')
    return false
  }
  
  try {
    stompClient.send(destination, {}, JSON.stringify(data))
    console.log(`[WebSocket] 已发送消息到 ${destination}:`, data)
    return true
  } catch (error) {
    console.error('[WebSocket] 发送消息失败:', error)
    return false
  }
}

/**
 * 获取连接状态
 */
export function getConnectionStatus() {
  return {
    isConnected,
    reconnectAttempts,
    subscriptions: Object.keys(subscriptions)
  }
}

/**
 * 重新连接
 */
export function reconnect() {
  disconnect()
  reconnectAttempts = 0
  connect()
}

/**
 * 切换设备订阅
 * @param {string} newDeviceId 新的设备ID
 */
export function switchDevice(newDeviceId) {
  if (newDeviceId === wsConfig.deviceId) {
    console.log('[WebSocket] 设备ID未变化，无需切换')
    return
  }
  
  console.log(`[WebSocket] 切换设备: ${wsConfig.deviceId} -> ${newDeviceId}`)
  wsConfig.deviceId = newDeviceId
  
  if (isConnected) {
    subscribeToDevice(newDeviceId)
  }
}

// 导出STOMP和SockJS供外部使用（如果需要自定义连接）
export { stompClient, socket, SockJS, Stomp }
