import website from '~src/config/index'
import { getObjValue, isNullES } from 'js-fast-way'

// 长链接推送插件
class HcSocket {

    constructor(data, change) {
        this.limit = website.socketLimit
        this.interval = website.socketInterval
        this.param = getObjValue(data)
        this.onChange = change
        this.socket = null
        this.isReconnecting = false
        this.connectionStatus = 'disconnected'
        this.isManualClosed = false
        if (this.validateParams()) {
            this.create()
            //this.handleMultipleTabs()
        }
    }

    validateParams() {
        const { projectId, contractId, userId } = this.param
        const { socket: socketUrl, clientId } = website
        return !(isNullES(socketUrl) || isNullES(clientId) || isNullES(projectId) || isNullES(contractId) || isNullES(userId))
    }

    //创建连接
    create() {
        const { projectId, contractId, userId } = this.param
        const { socket: socketUrl, clientId } = website

        const url = `${socketUrl}/${clientId}/${projectId}/${contractId}/${userId}`
        this.socket = new WebSocket(url)

        this.socket.onopen = this.handleOpen.bind(this)
        this.socket.onclose = this.handleClose.bind(this)
        this.socket.onmessage = this.handleMessage.bind(this)
        this.socket.onerror = this.handleError.bind(this)
    }

    handleOpen() {
        console.log('WebSocket 链接成功')
        this.connectionStatus = 'connected'
        this.isManualClosed = false
    }

    handleClose() {
        console.log('WebSocket 链接已断开')
        this.connectionStatus = 'disconnected'
        if (!this.isManualClosed) {
            this.reconnect()
        }
    }

    handleMessage({ data }) {
        try {
            const parsedData = JSON.parse(data)
            if (typeof this.onChange === 'function') {
                this.onChange(parsedData)
            }
        } catch (error) {
            console.error('解析 WebSocket 数据时出错:', error)
        }
    }

    handleError(error) {
        console.error('WebSocket 错误:', error)
        this.connectionStatus = 'error'
    }

    //发送消息
    send(data) {
        if (this.isSocket()) {
            this.socket.send(data)
        } else {
            console.warn('消息发送失败')
        }
    }

    //链接是否存在
    isSocket() {
        return !isNullES(this.socket) && (this.socket.readyState === WebSocket.OPEN)
    }

    //尝试重连
    async reconnect(attempts = 0) {
        if (this.isReconnecting || this.isManualClosed) return
        this.isReconnecting = true

        while (attempts < this.limit && !this.isSocket() && !this.isManualClosed) {
            console.log(`重新链接中... (${attempts + 1}/${this.limit})`)
            this.create()
            await new Promise(resolve => setTimeout(resolve, this.interval))
            attempts++
        }

        this.isReconnecting = false
        if (!this.isSocket() && !this.isManualClosed) {
            console.error('达到最大重连次数后仍然失败')
        }
    }

    handleMultipleTabs() {
        document.addEventListener('visibilitychange', this.handleVisibilityChange.bind(this))
    }

    // 处理多标签页问题
    handleVisibilityChange() {
        if (document.visibilityState === 'visible' && !this.isSocket() && !this.isManualClosed) {
            this.create()
        } else if (document.visibilityState === 'hidden') {
            this.close()
        }
    }

    //关闭或断开连接
    close() {
        this.isManualClosed = true
        if (this.isSocket()) {
            this.socket.close()
        }
        this.connectionStatus = 'disconnected'
    }

    destroy() {
        this.close()
        //document.removeEventListener('visibilitychange', this.handleVisibilityChange)
        this.socket = null
        this.onChange = null
    }
}

export { HcSocket }
