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

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

type SubmittedGameScore = {
    code: string
    score: 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
    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}`
}

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

export function sendGameMessage(cmd: string, data: any = {}) {
    return sendSocketMessage(cmd, data)
}
export const userJoinStatus = ref(false)

export function useGameSocket(options: GameSocketOptions) {
    const router = useRouter()
    let socket: Socket | null = null
    let offSocketMessage: (() => void) | undefined
    const domain = $read('domain', '');
    let resubmitcount = 0;

    socket = initSocket({
        socket_path: '/socket.io',
        client_ns: `${domain}/ws`,
        auth: options.auth,
        onConnect: (socket) => {
            options.onConnect?.();
        },
        onDisconnect: (_reason: string) => {
            // $toast('网络中断，尝试重新连接...')
            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') {
                //提交分数的情况下有问题的情况下,只重试3次
                if (resubmitcount >= 3) {
                    return;
                }
                setTimeout(() => {
                    resubmitcount++;
                    options.onRescoreSubmitted?.(resubmitcount);
                }, 200);
                return;
            }
            // debugger
            return;
        }

        if (state === 0) {
            // alert(msg)
            $toast(msg)
            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 != options.gameId) {
                    // debugger
                    return;
                }
                $toast('您已进入游戏房间')
                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 });
                break
            }
            case 'game_start_result': {
                if (data === options.gameId) {
                    options.onGameStart?.(data)
                }
                break
            }
            case 'submit_score_result': {
                options.onScoreSubmitted?.(false, data)
                break
            }
            case 'submit_score_save_result': {
                const submittedScore = options.onScoreSubmitted?.(true, data)
                const token = $getWechat()?.token_origin
                if (token && submittedScore && Number.isFinite(submittedScore.score)) {
                    void postScreenGameScore(token, submittedScore.code, submittedScore.score)
                }
                break
            }
            case 'room_back_result': {
                options.onRoomBack?.(data);
                break;
            }
            case 'room_close_result': {//管理员发送了房间关闭的消息
                $toast('管理员关闭了游戏房间,当前已断开连接');
                socket?.disconnect();
                break;
            }
            case 'room_rank_result': {
                //如果是游戏开始中再进入会收到这个排行榜消息
                options.onShowRank?.(data);
                return;
            }
            default: {
                debugger
            }
        }

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

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

    return {
        socket,
        userJoinStatus,
        offSocketMessage
    }
}
