<script setup lang="ts">
import { nextTick, onMounted, onUnmounted, ref, watch } from 'vue'
import { useRouter } from 'vue-router'
import Loading from './views/LoadingView.vue'
import Rank1 from './views/Rank1View.vue'
import Rank2 from './views/Rank2View.vue'
import { useAdminGameSocket } from '@/composables/useAdminGameSocket'
import type Player from '@/commons/player.ts'
import { playApplauseMusic, playGame6Music, stopAllMusic, stopGame6Music } from '@/commons/music'
import { $confirm, $remove_socket_storage, $notify, $toast } from '@/commons/utils.ts'

const router = useRouter()

type GameScreen = 'loading' | 'rank1' | 'rank2'

const PLAYER_LIMIT = 20
const RANK_LIMIT = 10

const emptyLoadingPlayer = () => ({
    score: '-',
    telephone: '',
    userid: '',
    wechat_id: '',
    nickname: '虚位以待',
    avatar: '',
})

const emptyRankPlayer = (index: number): Player => ({
    wechat_id: `empty-${index}`,
    nickname: '虚位以待',
    avatar: '',
    score: '-',
})

const screen = ref<GameScreen>('loading')
const loadingPlayers = ref<any[]>(Array.from({ length: PLAYER_LIMIT }, emptyLoadingPlayer))
const playerCount = ref(0)
const rankPlayers = ref<Player[]>(Array.from({ length: RANK_LIMIT }, (_, index) => emptyRankPlayer(index)))
const horseBoosts = ref<Record<string, number>>({});
const rank1Ref = ref<InstanceType<typeof Rank1> | null>(null)
let isPlayingStartAnimation = false

const confirmRefresh = (event: BeforeUnloadEvent) => {
    event.preventDefault()
    event.returnValue = ''
}

const renderPlayers = (data: any) => {
    const players = Array.isArray(data?.list) ? data.list : []
    playerCount.value = Number(data?.count ?? players.length)
    loadingPlayers.value = Array.from(
        { length: PLAYER_LIMIT },
        (_, index) => players[index] ?? emptyLoadingPlayer(),
    )
}

const updateRankPlayers = (data: any) => {
    // 兼容多种数据格式：纯数组 / {list:[]} / {players:[]} / {data:[]}
    let arr: any[] | null = null;
    if (Array.isArray(data)) {
        arr = data;
    } else if (Array.isArray(data?.list)) {
        arr = data.list;
    } else if (Array.isArray(data?.players)) {
        arr = data.players;
    } else if (Array.isArray(data?.data)) {
        arr = data.data;
    }

    if (!arr || arr.length === 0) {
        console.warn('[game3] updateRankPlayers: 无法解析排行数据', data);
        return;
    }

    // 打印第一条原始数据的所有字段名，用于排查字段不匹配问题
    console.log('[game3] updateRankPlayers: 收到排行数据', arr.length, '条, 第1条字段:', Object.keys(arr[0] || {}), ', 第1条值:', JSON.parse(JSON.stringify(arr[0])));

    // 将 WS 数据标准化为 Player 格式（同时保留 userid / wechat_id）
    // ⚠️ 当 WS 返回的数据没有 userid/openid/wechat_id 等ID字段时，用 avatar 作为唯一标识
    const normalized = arr.map((item: any, i: number) => {
        const hasId = item.userid || item.openid || item.user_id || item.wechat_id;
        const avatar = item.avatar || item.headimgurl || '';
        const nickname = item.nickname || item.name || '虚位以待';
        const isRealPlayer = nickname && nickname !== '-' && nickname !== '虚位以待';
        const wechat_id = hasId || (isRealPlayer && avatar ? `avt:${avatar}` : `empty-${i}`);
        return {
            ...item,
            userid: hasId || (isRealPlayer && avatar ? `avt:${avatar}` : ''),
            wechat_id,
            nickname,
            avatar,
            score: item.score ?? 0,
        };
    });

    rankPlayers.value = Array.from(
        { length: RANK_LIMIT },
        (_, index) => normalized[index] ?? emptyRankPlayer(index),
    );
}

const resetRoundState = () => {
    playerCount.value = 0
    loadingPlayers.value = Array.from({ length: PLAYER_LIMIT }, emptyLoadingPlayer)
    rankPlayers.value = Array.from({ length: RANK_LIMIT }, (_, index) => emptyRankPlayer(index))
    horseBoosts.value = {}
    isPlayingStartAnimation = false
}

const gotoLoading = (reset = false) => {
    if (reset) {
        resetRoundState()
    }

    screen.value = 'loading'
}

const gotoRank1WithIntro = async () => {
    if (isPlayingStartAnimation) return

    isPlayingStartAnimation = true
    // ⚠️ 不要用 seedRankPlayersFromLoading，由 WS room_rank_result 驱动马匹数据
    screen.value = 'rank1'
    await nextTick()
    await rank1Ref.value?.startIntro()

    isPlayingStartAnimation = false
}

function handleRoomState(data: any) {
    if (Array.isArray(data?.list)) {
        renderPlayers(data)
    }

    switch (data?.status) {
        case 0:
            gotoLoading(true)
            createRoom(3)
            break
        case 1:
            gotoLoading()
            break
        case 2:
            // 重连/中途进房时游戏已在运行，直接进入赛马画面
            if (isPlayingStartAnimation) break;
            isPlayingStartAnimation = true;
            screen.value = 'rank1'
            console.log('[game3] handleRoomState: status=2, 直接启动赛马动画');
            nextTick(() => {
                rank1Ref.value?.startIntro().finally(() => {
                    isPlayingStartAnimation = false;
                });
            });
            break
        case 3:
            screen.value = 'rank2'
            break
    }
}
const gameId='game3'
const { startGame, createRoom, backRoom, closeRoom } = useAdminGameSocket({
    gameId,
    onAny: (evt, payload) => {
        // 兜底处理所有非标准事件，解析玩家实时分数（对齐 game4）
        const data = payload?.data ?? payload;

        // 尝试从 data 中提取数组
        let arr: any[] | null = null;
        if (Array.isArray(data)) {
            arr = data;
        } else if (Array.isArray(data?.list)) {
            arr = data.list;
        } else if (Array.isArray(data?.data)) {
            arr = data.data;
        }

        if (arr && arr.length > 0) {
            const boosts: Record<string, number> = {};
            const normalized = arr.map((item: any, i: number) => {
                const hasId = item.userid || item.openid || item.user_id || item.wechat_id;
                const avatar = item.avatar || item.headimgurl || '';
                const nickname = item.nickname || item.name || '虚位以待';
                const isRealPlayer = nickname && nickname !== '-' && nickname !== '虚位以待';
                const wechat_id = hasId || (isRealPlayer && avatar ? `avt:${avatar}` : `empty-${i}`);
                return {
                    ...item,
                    userid: hasId || (isRealPlayer && avatar ? `avt:${avatar}` : ''),
                    wechat_id,
                };
            });

            const hasAnyPlayer = normalized.some((item: any) => {
                const id = item.userid || item.wechat_id || '';
                return !!id && !id.startsWith('empty-');
            });

            if (hasAnyPlayer) {
                // 同时更新 rankPlayers（确保马匹列表有真实玩家）
                rankPlayers.value = Array.from(
                    { length: RANK_LIMIT },
                    (_, index) => normalized[index] ?? emptyRankPlayer(index),
                );
            }

            normalized.forEach((item: any) => {
                const id = item.userid || item.wechat_id || '';
                if (!id || id.startsWith('empty-')) return;
                const raw = item.score ?? item.boost ?? item.acceleration ?? item.speed ?? item.progress;
                if (raw === undefined || raw === null) return;
                const val = Number(raw);
                if (isNaN(val)) return;
                boosts[id] = Math.max(0, val);
            });

            if (Object.keys(boosts).length > 0) {
                horseBoosts.value = { ...horseBoosts.value, ...boosts };
            }
        }
    },
    onRoomState: handleRoomState,
    onRoomJoin: (data) => {
        renderPlayers(data)
        gotoLoading()
    },
    onGameStart: gotoRank1WithIntro,
    onRoomRank: updateRankPlayers,
    onRelogin: async () => {
        $remove_socket_storage();
        await router.replace('/')
    }
})

const startGameWithMusic = () => {
    if (playerCount.value == 0) {
        // alert('房间中没有玩家')
        $toast('房间中没有玩家');
        return;
    }
    startGame()
}

const nextRound = () => {
    gotoLoading(true)
    //重开房间
    backRoom(3)
}

const nextRoundWithMusic = () => {
    nextRound()
}

const backHandler = async() => {
    const ok = await $confirm({
        title: '提示',
        message: '是否关闭当前房间回到首页',
        confirmText: '确定',
        cancelText: '取消',
    })
    if (ok) {
        closeRoom();
        stopAllMusic()
        router.replace('/main');
    }
}

onMounted(() => {
    window.addEventListener('beforeunload', confirmRefresh)
    playGame6Music()
})

onUnmounted(() => {
    stopAllMusic();
    window.removeEventListener('beforeunload', confirmRefresh)
})

watch(screen, (value) => {
    // console.log(value);
    if(value == 'rank2'){
        playApplauseMusic();
    }else if(value == 'loading'){
        playGame6Music();
    }
})
</script>

<template>
    <Loading v-if="screen === 'loading'" :players="loadingPlayers" :player-count="playerCount"
        @start="startGameWithMusic" @back="backHandler" />
    <Rank1 v-if="screen === 'rank1'" ref="rank1Ref" :rank-list="rankPlayers" :horse-boosts="horseBoosts"
        @start="startGameWithMusic" @next="nextRoundWithMusic" @back="backHandler" />
    <Rank2 v-if="screen === 'rank2'" :rank-list="rankPlayers" @next="nextRoundWithMusic" @back="backHandler" />
</template>
