import { ref } from 'vue'
import { useRouter } from 'vue-router'
import type { Socket } from 'socket.io-client'
import { initSocket, onSocketMessage, sendSocketMessage } from '@/commons/ws'
import { $alreadyRankedToast, $getWechat, $hideToast, $read, $save, $scoreSubmitFailedToast, $toast } from '@/commons/utils'

type SocketPayload = {
    msg?: string
    state?: number
    data?: any
}

type SubmittedGameScore = {
    code: string
    score: number,
    rank_no: number,
}

type GameSocketOptions = {
    gameId: string,
    auth: any,
    onConnect?: () => void,
    onShowRank?: (data: any) => void,
    onGameStart?: (data: any) => void
    onScoreSubmitted?: (is_save: boolean, data: any) => SubmittedGameScore | void
    onRescoreSubmitted?: (recount: number) => void
    onRoomClosed?: (data: any) => void
    onGameRecover?: (data: any) => void
    onStatus?: (data: any) => void
    onEvent?: (evt: string, payload: SocketPayload) => void
    onRoomBack?: (data: any) => void
}

function getGameIndex(data: any) {
    if (typeof data === 'object' && data !== null) {
        return Number(data.game ?? data.game_id ?? data.gameId ?? data.id)
    }

    return Number(data)
}

function getGameHomePath(data: any) {
    const gameIndex = getGameIndex(data)

    if (!Number.isInteger(gameIndex) || gameIndex <= 0) {
        return ''
    }

    return `/game${gameIndex}`
}

function getServerRank(data: any) {
    const value = typeof data === 'object' && data
        ? data.rank ?? data.rank_no ?? data.rankNo ?? data.game_rank ?? data.gameRank
        : data
    const rank = Number(value)
    return Number.isFinite(rank) && rank > 0 ? rank : 0
}

export function joinSharedRoom(nickname: string, token: string, avatar: string, gameId: string) {
    return sendSocketMessage('room_join', { nickname: nickname, token, avatar, gameId: gameId })
}

const networkDisconnectToastDuration = 30 * 60 * 1000;

export function sendGameMessage(cmd: string, data: any = {}) {
    const sent = sendSocketMessage(cmd, data)
    if (!sent && cmd === 'submit_score_save') {
        $scoreSubmitFailedToast(networkDisconnectToastDuration)
    }
    return sent
}

export function requestGameStatus() {
    return sendSocketMessage('status')
}
export const userJoinStatus = ref(false)
export const userTop10RankStatus = ref(false)
export const isGameSocketConnected = ref(false)

export function useGameSocket(options: GameSocketOptions) {
    const router = useRouter()
    let socket: Socket | null = null
    let offSocketMessage: (() => void) | undefined
    let statusTimer: ReturnType<typeof window.setInterval> | undefined
    const domain = $read('domain', '');
    let resubmitcount = 0;
    const stopStatusPolling = () => {
        if (statusTimer) {
            window.clearInterval(statusTimer)
            statusTimer = undefined
        }
    }

    const startStatusPolling = () => {
        stopStatusPolling()
        requestGameStatus()
        statusTimer = window.setInterval(requestGameStatus, 1000)
    }

    socket = initSocket({
        socket_path: '/socket.io',
        client_ns: `${domain}/ws`,
        auth: {
            ...options.auth,
            token: options.auth?.token ?? $getWechat()?.token_origin ?? '',
        },
        onConnect: (socket) => {
            isGameSocketConnected.value = true;
            $hideToast();
            startStatusPolling();
            options.onConnect?.();
        },
        onDisconnect: (_reason: string) => {
            // $toast('网络中断，尝试重新连接...')
            isGameSocketConnected.value = false;
            stopStatusPolling();
            socket = null;
        },
        onError: (error: any) => {
            // console.error('socket.io connect_error:', error)
        },
    })

    offSocketMessage = onSocketMessage((evt, payload: SocketPayload) => {
        const { msg, state, data } = payload
        if (state === 0) {
            if (evt == 'room_rank_result') {
                // options.show_rank?.(data);
                // return;
            }
            if (evt == 'connect_result') {
                // $toast(msg);
                // router.replace('/loading').then(() => { });
                return;
            }
            if (evt === 'room_join_result') {
                $toast(msg);
                // router.replace('/loading').then(() => { });
                return;
            }
            if (evt == 'submit_score_save_result') {
                //提交分数的情况下有问题的情况下,只重试3次
                if (resubmitcount >= 3) {
                    return;
                }
                setTimeout(() => {
                    resubmitcount++;
                    options.onRescoreSubmitted?.(resubmitcount);
                }, 200);
                return;
            }
            // debugger
            return;
        }

        switch (evt) {
            case 'room_create_result': {
                // if (`game${data}` == options.gameId) {
                //     // location.reload();
                //     options.onConnect?.();
                //     // debugger
                //     return;
                // }
                // const nextPath = getGameHomePath(data)

                // if (nextPath && router.currentRoute.value.path !== nextPath) {
                //     router.replace(nextPath)
                // }
                // break
            }
            case 'room_join_result': {
                if (data.gameId != options.gameId) {
                    // debugger
                    return;
                }
                //是否上过前十榜
                userTop10RankStatus.value = data.alreadyTopRanked
                $toast('您已进入游戏房间')
                userTop10RankStatus.value = data.alreadyTopRanked
                userJoinStatus.value = true
                break
            }
            case 'room_recover_result': {
                //游戏进行中玩家掉线重连时
                if (data.gameId != options.gameId) {
                    return;
                }
                userJoinStatus.value = true
                let { rank, remainingSeconds, score } = data;
                //返回的时间可能会慢一秒
                options.onGameRecover?.({ rank, remainingSeconds, score });
                options.onGameRecover?.({ rank, remainingSeconds, score });
                break
            }
            case 'game_start_result': {
                if (data.index === options.gameId) {
                    $save('batch_no', data.batch_no);
                    options.onGameStart?.(data)
                }
                break
            }
            case 'submit_score_result': {
                options.onScoreSubmitted?.(false, data)
                break
            }
            case 'submit_score_save_result': {
                options.onScoreSubmitted?.(true, data)
                break
            }
            case 'status_result': {
                if (data?.gameId && data.gameId !== options.gameId) {
                    return
                }
                options.onStatus?.(data)
                break
            }
            case 'room_back_result': {
                options.onRoomBack?.(data);
                break;
            }
            case 'room_close_result': {//管理员发送了房间关闭的消息
                $toast('管理员关闭了游戏房间,当前已断开连接');
                socket?.disconnect();
                break;
            }
            case 'room_rank_result': {
                //如果是游戏开始中再进入会收到这个排行榜消息
                options.onShowRank?.(data);
                options.onShowRank?.(data);
                return;
            }
            default: {
                debugger
            }
        }

        options.onEvent?.(evt, payload)
    })

    // onBeforeUnmount(() => {
    //     offSocketMessage?.()
    // })

    return {
        socket,
        userJoinStatus,
        userTop10RankStatus,
        requestGameStatus,
        offSocketMessage: () => {
            stopStatusPolling()
            offSocketMessage?.()
        }
    }
}
