// WebSocket 连接状态
export type WsStatus =
// 空闲未连接
    | 'idle'
    // 正在连接
    | 'connecting'
    // 连接成功
    | 'connected'
    // 连接已关闭
    | 'closed'
    // 连接异常
    | 'error'

// 消息回调
type MessageHandler = (data: any) => void
// 状态变化回调
type StatusHandler = (status: WsStatus) => void
// 错误回调
type ErrorHandler = (err: string) => void

class WsClient {
    private ws: WebSocket | null = null
    private url: string = ''
    private token: string = '' // 保存 token（用于重连）

    private status: WsStatus = 'idle'

    private messageHandlers: MessageHandler[] = []
    private statusHandlers: StatusHandler[] = []
    private errorHandlers: ErrorHandler[] = []

    private reconnectTimer: number | null = null
    private reconnectDelay = 2000 // 重连间隔（毫秒）
    private manualClosing = false


    // 构造带 token 的 URL
    private buildUrl(): string {
        if (!this.token) return this.url

        const hasQuery = this.url.includes('?')
        const connector = hasQuery ? '&' : '?'

        return `${this.url}${connector}token=${encodeURIComponent(this.token)}`
    }


    // 建立连接
    connect(url: string, token?: string) {
        // 已连接或连接中则不重复连接
        if (this.ws && (this.status === 'connected' || this.status === 'connecting')) {
            return
        }

        this.url = url
        if (token !== undefined) {
            this.token = token // 保存 token（用于重连）
        }

        this.setStatus('connecting')
        this.manualClosing = false

        const finalUrl = this.buildUrl()
        this.ws = new WebSocket(finalUrl)

        // 连接成功
        this.ws.onopen = () => {
            this.setStatus('connected')
        }

        // 收到消息
        this.ws.onmessage = (event) => {
            try {
                const data = JSON.parse(event.data)
                this.messageHandlers.forEach(fn => fn(data))
            } catch {
                this.messageHandlers.forEach(fn => fn(event.data))
            }
        }

        // 出错
        this.ws.onerror = () => {
            this.setStatus('error')
            this.emitError('WebSocket error')
        }

        // 连接关闭
        this.ws.onclose = () => {
            this.setStatus('closed')
            if (!this.manualClosing) {
                this.tryReconnect()
            }
            this.manualClosing = false
        }
    }


    // 发送消息
    send(data: any) {
        if (this.ws && this.status === 'connected') {
            this.ws.send(JSON.stringify(data))
        }
    }


    // 手动关闭
    close() {
        this.manualClosing = true
        if (this.ws) {
            this.ws.close()
            this.ws = null
        }
        this.clearReconnect()
    }

    reconnect(url: string, token?: string) {
        this.close()
        this.connect(url, token)
    }


    // 订阅消息
    onMessage(handler: MessageHandler) {
        this.messageHandlers.push(handler)
    }

    // 订阅状态变化
    onStatusChange(handler: StatusHandler) {
        this.statusHandlers.push(handler)
        return () => {
            this.statusHandlers = this.statusHandlers.filter(fn => fn !== handler)
        }
    }

    // 订阅错误
    onError(handler: ErrorHandler) {
        this.errorHandlers.push(handler)
    }


    // 设置状态并通知所有订阅者
    private setStatus(status: WsStatus) {
        this.status = status
        this.statusHandlers.forEach(fn => fn(status))
    }

    // 触发错误回调
    private emitError(msg: string) {
        this.errorHandlers.forEach(fn => fn(msg))
    }

    // 尝试重连
    private tryReconnect() {
        this.clearReconnect()

        this.reconnectTimer = window.setTimeout(() => {
            if (this.url) {
                this.connect(this.url) // 自动带 token
            }
        }, this.reconnectDelay)
    }

    // 清除重连定时器
    private clearReconnect() {
        if (this.reconnectTimer !== null) {
            window.clearTimeout(this.reconnectTimer)
            this.reconnectTimer = null
        }
    }
}

// 单例
export const wsClient = new WsClient()
