// utils/sse.ts
import { request } from './request'
import { BASE_URL } from '../env'

//唯一id
const sign = Date.now().toString(36) + Math.random().toString(36).slice(2)
const listeners: Record<string, ((data: any) => void)[]> = {}

let requestTask: any = null
let reconnectTimer: any = null
let requestTimer: any = null


// 不支持TextDecoder的话手动转码utf8
function utf8Decode(uint8: Uint8Array): string {
    let str = '';
    let i = 0;
    while (i < uint8.length) {
        const byte1 = uint8[i];
        let charCode = byte1;
        if (byte1 <= 0x7F) {
            i += 1;
        } else if (byte1 >= 0xC0 && byte1 <= 0xDF) {
            const byte2 = uint8[i + 1];
            charCode = ((byte1 & 0x1F) << 6) | (byte2 & 0x3F);
            i += 2;
        } else if (byte1 >= 0xE0 && byte1 <= 0xEF) {
            const byte2 = uint8[i + 1];
            const byte3 = uint8[i + 2];
            charCode = ((byte1 & 0x0F) << 12) | ((byte2 & 0x3F) << 6) | (byte3 & 0x3F);
            i += 3;
        } else if (byte1 >= 0xF0 && byte1 <= 0xF7) {
            const byte2 = uint8[i + 1];
            const byte3 = uint8[i + 2];
            const byte4 = uint8[i + 3];
            charCode = ((byte1 & 0x07) << 18) | ((byte2 & 0x3F) << 12) | ((byte3 & 0x3F) << 6) | (byte4 & 0x3F);
            i += 4;
        }
        str += String.fromCharCode(charCode);
    }
    return str;
}

export function startSSE() {
    if (requestTimer) return //已经启动过就不重复
    // if (wx.getStorageSync("sseId")) leave();
    wx.setStorageSync("sseId", sign)
    requestSSE()
    //30s连接一次,保持连接
    // requestTimer = setInterval(() => {
    //     requestSSE()
    // }, 30000)
}

async function requestSSE() {
    try {
        requestTask = (wx as any).request({
            url: `${BASE_URL}/api/auth/message/subscribe/${sign}`,
            method: 'GET',
            enableChunked: true,
            responseType: 'arraybuffer',
            header: { 'Content-Type': 'application/json' },
        })

        requestTask?.onChunkReceived?.((chunk: any) => {
            const uint8 = new Uint8Array(chunk.data)
            let chunkStr = ''
            try {
                //真机环境不支持TextDecoder
                // @ts-ignore
                chunkStr = new TextDecoder('utf-8').decode(uint8);
            } catch {
                chunkStr = utf8Decode(uint8);
            }
            const lines = chunkStr.trim().split('\n')
            for (const line of lines) {
                try {
                 //   console.log(JSON.parse(line), 'lllllll')
                    if (JSON.parse(line).msg == 'auto close') {
                        requestSSE()
                    }
                } catch {
                    if (line.startsWith('data:')) {
                        try {
                            const json = JSON.parse(line.slice(5))
                            const app = getApp<IAppOption>()
                            const data = json.data
                            const eventName = json.event
                            //分类保存
                            if (data && data.type) {
                                if (!app.globalData.sseStore) app.globalData.sseStore = {}
                                if (!app.globalData.sseStore[data.type]) app.globalData.sseStore[data.type] = []

                                //可能会传sku对应商品，直播评论，分类的通知
                                //存入传入的数组
                                app.globalData.sseStore[data.type].push(data)

                                //最多只保留100条
                                if (app.globalData.sseStore[data.type].length > 100) {
                                    app.globalData.sseStore[data.type].shift()
                                }
                            }

                            if (eventName && listeners[eventName]) {
                                listeners[eventName].forEach(fn => fn(data))
                            }

                        } catch (err) {
                            console.error('解析返回数据失败:', err)
                        }
                    }
                }

            }
        })
    } catch (err) {
        console.warn('sse请求失败:', err)
    }

    requestTask.onError?.((err: any) => {
        console.warn('sse连接出错，5秒后重连', err)
        scheduleReconnect()
    })

    requestTask.then?.(() => {
        console.log('sse连接出错，5秒后重连')
        scheduleReconnect()
    })
}

//注册事件监听
export function addCustomEventListener(eventName: string, fn: (data: any) => void) {
    if (!listeners[eventName]) listeners[eventName] = []
    listeners[eventName].push(fn)
}

//移除事件监听
export function removeCustomEventListener(eventName: string, fn: (data: any) => void) {
    if (!listeners[eventName]) return
    listeners[eventName] = listeners[eventName].filter(f => f !== fn)
    if (listeners[eventName].length === 0) delete listeners[eventName]
}

//加入频道
export async function join(name: string) {
    const app = getApp<IAppOption>();
    try {
        if (app.globalData.joinedArray.includes(name)) {
            return;  //加入过就不加入了
        }
        app.globalData.joinedArray = [name, ...app.globalData.joinedArray]; //为什么在request后就不能push了？？
        await request({
            options: {
                url: `/auth/message/join`,
                method: 'POST',
                data: { id: sign, name }
            },
            isLoading: false
        })
    } catch {
        app.globalData.joinedArray = app.globalData.joinedArray.filter(item => item !== name);
    }

}

//离开频道
export async function leave(name: string) {
    const app = getApp<IAppOption>()
    try {
        app.globalData.joinedArray = app.globalData.joinedArray.filter(item => item !== name);
        await request({
            options: {
                url: `/auth/message/leave`,
                method: 'POST',
                data: { id: wx.getStorageSync('sseId'), name }
                // data: { id: wx.getStorageSync('sseId'), name: String(shopId) }
            },
            isLoading: false
        })
    } catch {
        app.globalData.joinedArray = [name, ...app.globalData.joinedArray];
    }

}


//重连
function scheduleReconnect() {
    stopSSE()
    reconnectTimer = setTimeout(() => {
        console.log('重连sse中...')
        startSSE()
    }, 5000)
}


//停止sse
export function stopSSE() {
    if (requestTask) {
        requestTask.abort?.()
        requestTask = null
    }
    clearTimeout(reconnectTimer)
}

//获取sse的某个分类数据
export function getSSEStore(type: string) {
    const app = getApp<IAppOption>()
    return app.globalData.sseStore[type] || []
}

//删除sse的某个分类数据
export function clearSSEStore(type?: string) {
    const app = getApp<IAppOption>()
    if (type) {
        app.globalData.sseStore[type] = []
    } else {
        Object.keys(app.globalData.sseStore).forEach(k => {
            app.globalData.sseStore[k] = []
        })
    }
}