import { BASE_URL } from '../config'

export interface SocketMessage {
  type?: string
  title?: string
  content?: string
  businessId?: number
  senderId?: number
  senderName?: string
  targetType?: string
  targetRole?: string
  targetUserId?: number
  targetTeamId?: number
  sendTime?: string
  extra?: any
  [key: string]: any
}

type MessageHandler = (message: SocketMessage) => void

const HEARTBEAT_INTERVAL = 30000 // 心跳间隔 30s
const HEARTBEAT_TIMEOUT = 10000 // 心跳超时 10s
const MAX_RECONNECT_DELAY = 30000 // 最大重连间隔 30s

let socketTask: UniApp.SocketTask | null = null
let messageHandlers: MessageHandler[] = []
let heartbeatTimer: number | null = null
let heartbeatTimeoutTimer: number | null = null
let reconnectTimer: number | null = null
let reconnectAttempts = 0
let isManualClose = false
let currentUrl = ''

function buildWebSocketUrl(token: string): string {
  const wsUrl = BASE_URL.replace(/^http/, 'ws').replace(/\/$/, '')
  return `${wsUrl}/ws/notify?token=${encodeURIComponent(token)}`
}

function resetHeartbeat() {
  if (heartbeatTimer) {
    clearInterval(heartbeatTimer)
    heartbeatTimer = null
  }
  if (heartbeatTimeoutTimer) {
    clearTimeout(heartbeatTimeoutTimer)
    heartbeatTimeoutTimer = null
  }
}

function startHeartbeat() {
  resetHeartbeat()
  heartbeatTimer = setInterval(() => {
    if (!socketTask) return
    try {
      socketTask.send({ data: JSON.stringify({ type: 'ping' }) })
      heartbeatTimeoutTimer = setTimeout(() => {
        console.warn('WebSocket 心跳超时，准备重连')
        reconnect()
      }, HEARTBEAT_TIMEOUT)
    } catch (e) {
      console.error('发送心跳失败', e)
      reconnect()
    }
  }, HEARTBEAT_INTERVAL)
}

function scheduleReconnect() {
  if (isManualClose) return
  if (reconnectTimer) return

  const delay = Math.min(1000 * Math.pow(2, reconnectAttempts), MAX_RECONNECT_DELAY)
  reconnectAttempts++

  reconnectTimer = setTimeout(() => {
    reconnectTimer = null
    reconnect()
  }, delay)
}

function reconnect() {
  if (isManualClose || !currentUrl) return
  console.log(`WebSocket 尝试重连... (第${reconnectAttempts}次)`)
  close()
  connect(currentUrl)
}

export function connect(token: string) {
  if (socketTask) {
    console.log('WebSocket 已连接，跳过')
    return
  }

  // 清空旧的消息处理器，避免重复订阅
  messageHandlers = []

  const url = buildWebSocketUrl(token)
  currentUrl = url
  isManualClose = false

  console.log('WebSocket 连接中...', url)

  socketTask = uni.connectSocket({
    url,
    success: () => {
      console.log('WebSocket connectSocket 调用成功')
    },
    fail: (err) => {
      console.error('WebSocket connectSocket 调用失败', err)
      socketTask = null
      scheduleReconnect()
    },
  })

  socketTask.onOpen(() => {
    console.log('WebSocket 连接已打开')
    reconnectAttempts = 0
    startHeartbeat()
  })

  socketTask.onMessage((res) => {
    try {
      const data = JSON.parse(res.data as string) as SocketMessage
      // 处理心跳响应
      if (data.type === 'pong' || data.type === 'connected') {
        if (heartbeatTimeoutTimer) {
          clearTimeout(heartbeatTimeoutTimer)
          heartbeatTimeoutTimer = null
        }
        return
      }
      messageHandlers.forEach((handler) => {
        try {
          handler(data)
        } catch (e) {
          console.error('WebSocket 消息处理器异常', e)
        }
      })
    } catch (e) {
      console.warn('WebSocket 收到非JSON消息', res.data)
    }
  })

  socketTask.onClose(() => {
    console.log('WebSocket 连接已关闭')
    socketTask = null
    resetHeartbeat()
    scheduleReconnect()
  })

  socketTask.onError((err) => {
    console.error('WebSocket 错误', err)
    socketTask = null
    resetHeartbeat()
    scheduleReconnect()
  })
}

export function send(data: any) {
  if (!socketTask) {
    console.warn('WebSocket 未连接，无法发送消息')
    return
  }
  socketTask.send({
    data: typeof data === 'string' ? data : JSON.stringify(data),
  })
}

export function close() {
  isManualClose = true
  resetHeartbeat()
  if (reconnectTimer) {
    clearTimeout(reconnectTimer)
    reconnectTimer = null
  }
  if (socketTask) {
    try {
      socketTask.close({})
    } catch (e) {
      console.error('关闭 WebSocket 失败', e)
    }
    socketTask = null
  }
}

export function onMessage(handler: MessageHandler) {
  messageHandlers.push(handler)
  return () => {
    messageHandlers = messageHandlers.filter((h) => h !== handler)
  }
}

export function isConnected(): boolean {
  return socketTask !== null
}

export function resetReconnectAttempts() {
  reconnectAttempts = 0
}

// 网络恢复或 App 回到前台时尝试重连
export function ensureConnected(token: string) {
  if (!isConnected() && !isManualClose) {
    connect(token)
  }
}
