<script setup lang="ts">
import { ref, watch, onMounted, onUnmounted } from 'vue'
import DesignStage from '../../../components/DesignStage.vue'
import type Player from '../../../commons/player.ts'
import { $format_str, $is_run_local } from '@/commons/utils.ts'
import { assetUrl, cssAssetUrl } from '@/commons/assets.ts'
import { playApplauseMusic, stopApplauseMusic } from '@/commons/music'

const props = defineProps<{
    rankList: Player[];
    horseBoosts: Record<string, number>;
}>();

const emit = defineEmits<{
    start: [];
    next: [];
    back: [];
}>();

const RANK_LIMIT = 10;
const designStage = ref<InstanceType<typeof DesignStage> | null>(null);
const gameStarted = ref(false);
const isGameRunning = ref(false);
const showResult = ref(false);

const imageUrls = {
    bg: cssAssetUrl('game3/bg2.webp'),
    logo: cssAssetUrl('game1/logo.png'),
    title: cssAssetUrl('game3/title2.webp'),
    username: cssAssetUrl('game4/username.svg'),
    defaultAvatar: assetUrl('game4/default-avator.svg'),
    resultBg: cssAssetUrl('game6/bg3.png'),
    resultTitle: cssAssetUrl('game6/title3.png'),
    podium: cssAssetUrl('game6/podium.png'),
    vip: cssAssetUrl('game6/vip.png'),
    avatar: cssAssetUrl('avatar-yellow.png'),
    avatarAnimation: cssAssetUrl('avatar-yellow_animation.png'),
    rankIcon: cssAssetUrl('game6/no4.png'),
    next: cssAssetUrl('game1/next.png'),
    back: cssAssetUrl('game1/back.png'),
};

// ========== 马匹帧配置（只用 ma1/ma2/ma3，不用 ma4） ==========
const HORSE_SIZE = 280;
const HORSE_START_X = -HORSE_SIZE;
const HORSE_END_X = 1920;

const horseFrameConfigs = [
    { type: 1, dir: 'game3/ma1', prefix: '1ma_', startIndex: 24, count: 12 },
    { type: 2, dir: 'game3/ma2', prefix: '2ma_', startIndex: 24, count: 12 },
    { type: 3, dir: 'game3/ma3', prefix: '3ma_', startIndex: 12, count: 14 },
];

const HORSE_TYPES = [1, 2, 3] as const;

const horseFrames: Record<number, string[]> = {};
const horseFrameCount: Record<number, number> = {};
for (const config of horseFrameConfigs) {
    horseFrames[config.type] = Array.from({ length: config.count }, (_, i) =>
        assetUrl(`${config.dir}/${config.prefix}${String(config.startIndex + i).padStart(5, '0')}.png`),
    );
    horseFrameCount[config.type] = config.count;
}

interface Horse {
    id: string;
    horseType: number;
    lane: number;
    frameIndex: number;
    frameTimer: number;
    x: number;
    targetX: number;
    nickname: string;
    avatar: string;
    wechat_id: string;  // 用于匹配 WebSocket 实时排名数据
}

const horses = ref<Horse[]>([]);
let horseIdCounter = 0;

// ========== 排名相关 ==========
const emptyPlayer = (index: number): Player => ({
    wechat_id: `empty-${index}`,
    nickname: '-',
    avatar: '',
    score: 0,
});

const list = ref<Player[]>(Array.from({ length: RANK_LIMIT }, (_, index) => emptyPlayer(index)));
const playerKey = (player: Player, index = 0) => player.userid || player.wechat_id || `empty-${index}`;

const updateRankList = (rankList: Player[]) => {
    const next = Array.from({ length: RANK_LIMIT }, (_, index) => rankList[index] ?? emptyPlayer(index));
    list.value = next;
};

// 玩家实时分数（合并 rankList + horseBoosts 双通道，对齐 game4 模式）
const liveScores = ref<Record<string, number>>({});

watch(
    () => props.rankList,
    (rankList) => {
        console.log('[game3 Rank1View] websocket rankList 数据:', JSON.parse(JSON.stringify(rankList)));
        updateRankList(rankList);
        // 游戏进行中，实时更新马匹玩家列表（处理加入/离开）
        if (isGameRunning.value) {
            updateHorses(rankList);
        }
    },
    { immediate: true, deep: true },
);

watch(
    () => props.horseBoosts,
    (boosts) => {
        if (!boosts || Object.keys(boosts).length === 0) return;
        const merged = { ...liveScores.value };
        for (const [id, score] of Object.entries(boosts)) {
            // 取较大的值，因为不同通道可能收到不同时间点的数据
            if (score > (merged[id] ?? 0)) {
                merged[id] = score;
            }
        }
        liveScores.value = merged;
    },
    { deep: true },
);

// ========== 马匹动画循环 (RAF 驱动帧切换 + 分数驱动位移) ==========
let horseRafId: number | undefined;
let horseLastTs = 0;
const HORSE_FRAME_TICK_MS = 48;
// 慢速 lerp，分数变化时马匹平滑过渡（约 2.5s 拉到位）
const HORSE_LERP_SPEED = 2.5;

const startHorseLoop = () => {
    stopHorseLoop();
    horseLastTs = 0;

    const tick = (ts: number) => {
        if (!isGameRunning.value) {
            horseRafId = requestAnimationFrame(tick);
            return;
        }
        if (!horseLastTs) horseLastTs = ts;
        const dt = Math.min(ts - horseLastTs, 200);
        horseLastTs = ts;

        if (horses.value.length === 0) {
            horseRafId = requestAnimationFrame(tick);
            return;
        }

        // 优先用 liveScores（onAny 实时数据），回退到 list 分数
        const getScore = (wechatId: string): number => {
            const liveScore = liveScores.value[wechatId];
            if (typeof liveScore === 'number' && liveScore > 0) return liveScore;
            const player = list.value.find(p => p.wechat_id === wechatId);
            return typeof player?.score === 'number' ? player.score : 0;
        };

        // 计算当前最高分
        let maxScore = 0;
        for (const horse of horses.value) {
            const s = getScore(horse.wechat_id);
            if (s > maxScore) maxScore = s;
        }
        if (maxScore <= 0) maxScore = 1;

        for (const horse of horses.value) {
            const score = getScore(horse.wechat_id);

            // 进度 = 最小 5% + 根据分数占比最大 95%
            const progress = 0.05 + (score / maxScore) * 0.95;
            horse.targetX = HORSE_START_X + (HORSE_END_X - HORSE_START_X) * progress;

            // 平滑 lerp，分数变化不跳变
            const lerpFactor = 1 - Math.pow(0.001, dt / (1000 * HORSE_LERP_SPEED));
            horse.x += (horse.targetX - horse.x) * lerpFactor;

            // 帧动画
            const fc = horseFrameCount[horse.horseType] ?? 12;
            horse.frameTimer += dt;
            while (horse.frameTimer >= HORSE_FRAME_TICK_MS) {
                horse.frameTimer -= HORSE_FRAME_TICK_MS;
                horse.frameIndex = (horse.frameIndex + 1) % fc;
            }
        }

        horseRafId = requestAnimationFrame(tick);
    };
    horseRafId = requestAnimationFrame(tick);
};

const stopHorseLoop = () => {
    if (horseRafId) {
        cancelAnimationFrame(horseRafId);
        horseRafId = undefined;
    }
};

// ========== 生成/更新马匹（对齐 game4 updateHorses 模式，保留已有马匹进度） ==========
const LANE_TOP_POSITIONS = [480, 640, 800];

const updateHorses = (players: Player[]) => {
    const validPlayers = players.filter(p => {
        if (!p || !p.wechat_id) return false;
        if (p.wechat_id.startsWith('empty-')) return false;
        if (p.nickname === '-' || p.nickname === '虚位以待') return false;
        return true;
    });

    if (validPlayers.length === 0) {
        horses.value = [];
        return;
    }

    // 保留已有马匹的 x 位置，防止重新生成时位置跳变
    const existingMap = new Map(horses.value.map(h => [h.wechat_id, h]));

    horses.value = validPlayers.map((player, index) => {
        const wid = player.wechat_id || '';
        const existing = existingMap.get(wid);
        return {
            id: existing?.id || `horse-${++horseIdCounter}`,
            horseType: HORSE_TYPES[index % HORSE_TYPES.length]!,
            lane: index % LANE_TOP_POSITIONS.length,
            frameIndex: existing?.frameIndex ?? Math.floor(Math.random() * (horseFrameCount[HORSE_TYPES[index % HORSE_TYPES.length]!] ?? 12)),
            frameTimer: existing?.frameTimer ?? 0,
            x: existing?.x ?? HORSE_START_X,
            targetX: existing?.targetX ?? HORSE_START_X,
            nickname: player.nickname || '',
            avatar: player.avatar || '',
            wechat_id: wid,
        };
    });
};

// ========== 预加载马匹帧 ==========
const preloadHorseFrames = () => {
    for (const frames of Object.values(horseFrames)) {
        for (const url of frames) {
            const img = new Image();
            img.src = url;
        }
    }
};

// ========== 游戏流程 ==========
const startIntro = async () => {
    showResult.value = false;
    gameStarted.value = false;
    isGameRunning.value = false;
    horses.value = [];
    horseIdCounter = 0;
    stopApplauseMusic();
    preloadHorseFrames();

    const countdownPromise = designStage.value?.startCountdown(3, 60);
    await new Promise((r) => setTimeout(r, 3500));

    gameStarted.value = true;
    isGameRunning.value = true;
    updateHorses(list.value);
    startHorseLoop();

    await countdownPromise;
    stopGame();
};

const stopGame = () => {
    isGameRunning.value = false;
    showResult.value = true;
    stopHorseLoop();
    playApplauseMusic();
    console.log('[game3 Rank1View] 游戏结束，显示结果页');
};

defineExpose({
    startIntro,
});

// ========== 头像样式 ==========
const horseAvatarStyle = (horse: Horse) => {
    if (horse.avatar) {
        return { backgroundImage: `url(${horse.avatar})`, backgroundSize: 'cover' };
    }
    return { backgroundImage: `url(${imageUrls.defaultAvatar})`, backgroundSize: 'cover' };
};

const renderAvatar = (item: any | null) => {
    if (item && item.avatar) {
        return `background: url("${String(item.avatar).replace(/"/g, '\\"')}") center / cover no-repeat;`
    }
    return `background: ${imageUrls.avatar} center / cover no-repeat;`
};

onMounted(() => {
    preloadHorseFrames();
    if ($is_run_local()) {
        // 本地模式：用模拟玩家填充 list，驱动马匹渲染
        list.value = [
            { wechat_id: 'local-1', nickname: '骑手一', avatar: '', score: 45 },
            { wechat_id: 'local-2', nickname: '骑手二', avatar: '', score: 38 },
            { wechat_id: 'local-3', nickname: '骑手三', avatar: '', score: 30 },
            { wechat_id: 'local-4', nickname: '骑手四', avatar: '', score: 22 },
            { wechat_id: 'local-5', nickname: '骑手五', avatar: '', score: 15 },
        ];
        gameStarted.value = true;
        isGameRunning.value = true;
        updateHorses(list.value);
        startHorseLoop();
        // 模拟分数变化
        let simTick = 0;
        const simInterval = setInterval(() => {
            if (!isGameRunning.value) { clearInterval(simInterval); return; }
            simTick++;
            // 随机涨分
            for (const p of list.value) {
                if (typeof p.score === 'number') {
                    p.score += Math.floor(Math.random() * 3);
                }
            }
        }, 1500);
    }
});

onUnmounted(() => {
    stopGame();
    stopApplauseMusic();
});
</script>

<template>
    <DesignStage ref="designStage">
        <div class="screen-container" :class="{ paused: !gameStarted }">
            <!-- 背景层：无缝滚动 -->
            <div class="bg-track">
                <div class="bg-inner"></div>
                <div class="bg-inner"></div>
            </div>

            <!-- Logo & Title -->
            <div class="img-logo"></div>
            <div class="img-title"></div>

            <!-- 马匹 -->
            <template v-if="gameStarted && !showResult">
                <div
                    v-for="horse in horses"
                    :key="horse.id"
                    class="horse-wrapper"
                    :style="{
                        top: `${LANE_TOP_POSITIONS[horse.lane]}px`,
                        transform: `translateX(${horse.x}px)`,
                    }"
                >
                    <div class="horse-sprite">
                        <img
                            v-for="(url, frameIdx) in horseFrames[horse.horseType]"
                            :key="frameIdx"
                            :src="url"
                            class="horse-frame"
                            :class="{ active: frameIdx === horse.frameIndex }"
                            alt=""
                        />
                    </div>
                    <div class="horse-shadow"></div>
                    <div class="horse-avatar" :style="horseAvatarStyle(horse)"></div>
                    <div class="horse-username">
                        <span class="username-text">{{ $format_str(horse.nickname, 8) }}</span>
                    </div>
                </div>
            </template>

            <!-- 结果页（参考 game6 Rank2View） -->
            <div v-if="showResult" class="result-overlay">
                <div class="result-bg"></div>
                <div class="result-logo"></div>
                <div class="result-title"></div>

                <div class="podium">
                    <div class="img-vip"></div>
                    <div class="rank-no1">
                        <div class="avatar" :style="`${renderAvatar(list[0])}`"></div>
                        <div class="nickname">{{ list[0]?.nickname }}</div>
                    </div>
                    <div class="rank-no2">
                        <div class="avatar" :style="`${renderAvatar(list[1])}`"></div>
                        <div class="nickname">{{ list[1]?.nickname }}</div>
                    </div>
                    <div class="rank-no3">
                        <div class="avatar" :style="`${renderAvatar(list[2])}`"></div>
                        <div class="nickname">{{ list[2]?.nickname }}</div>
                    </div>
                </div>

                <div class="rank-container">
                    <div v-for="(item, index) in list.slice(3)" :key="item.userid || item.wechat_id || `rank-${index}`">
                        <div class="no-icon">{{ index + 4 }}</div>
                        <div>
                            <div class="img-avatar-container">
                                <div class="img-avatar" :style="`${renderAvatar(list[index + 3])}`"></div>
                            </div>
                            <div class="txt-nickname">{{ item.nickname }}</div>
                        </div>
                    </div>
                </div>

                <div class="btn-next" @click="emit('next')"></div>
                <div class="btn-back" @click="emit('back')"></div>
            </div>
        </div>
    </DesignStage>
</template>

<style scoped>
.screen-container {
    width: 1920px;
    height: 1080px;
    position: relative;
    overflow: hidden;
}

.screen-container.paused .bg-track {
    animation-play-state: paused;
}

/* ========== 背景无缝滚动 ========== */
.bg-track {
    width: 3840px;
    height: 1080px;
    position: absolute;
    top: 0;
    left: 0;
    display: flex;
    animation: bg-scroll-left 30s linear infinite;
    z-index: 0;
}

.bg-inner {
    width: 1920px;
    height: 1080px;
    background: v-bind('imageUrls.bg') center / cover no-repeat;
    flex-shrink: 0;
}

@keyframes bg-scroll-left {
    0% {
        transform: translateX(0);
    }
    100% {
        transform: translateX(-1920px);
    }
}

.img-logo {
    background: v-bind('imageUrls.logo');
    background-size: cover;
    width: 428px;
    height: 77px;
    position: absolute;
    left: 37px;
    top: 82px;
    z-index: 20;
}

.img-title {
    background: v-bind('imageUrls.title') center / cover no-repeat;
    width: 544px;
    height: 208px;
    position: absolute;
    left: 679px;
    top: 52px;
    z-index: 20;
}

/* ========== 马匹 ========== */
.horse-wrapper {
    position: absolute;
    left: 0;
    width: 280px;
    height: 280px;
    z-index: 15;
}

.horse-sprite {
    position: relative;
    width: 280px;
    height: 280px;
}

.horse-frame {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: contain;
    opacity: 0;
    pointer-events: none;
    z-index: 1;
}

.horse-frame.active {
    opacity: 1;
}

.horse-shadow {
    position: absolute;
    bottom: 20px;
    left: 50%;
    transform: translateX(-50%);
    width: 180px;
    height: 24px;
    background: radial-gradient(ellipse, rgba(0, 0, 0, 0.4) 0%, transparent 70%);
    border-radius: 50%;
    pointer-events: none;
    z-index: 0;
}

/* ========== 马背用户信息 ========== */
.horse-avatar {
    width: 50px;
    height: 50px;
    border-radius: 50%;
    position: absolute;
    top: 80px;
    left: 60px;
    border: 2px solid #FFCF44;
    z-index: 3;
}

.horse-username {
    background: v-bind('imageUrls.username');
    background-size: contain;
    background-repeat: no-repeat;
    width: 120px;
    height: 44px;
    padding-left: 12px;
    position: absolute;
    top: 105px;
    left: 60px;
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 2;
}

.username-text {
    position: absolute;
    top: 2px;
    color: #000;
    font-size: 16px;
    font-weight: bold;
    max-width: 100px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    padding-left: 4px;
    box-sizing: border-box;
}

/* ========== 结果页（参考 game6 Rank2View） ========== */
.result-overlay {
    width: 1920px;
    height: 1080px;
    position: absolute;
    top: 0;
    left: 0;
    z-index: 100;
}

.result-bg {
    width: 1920px;
    height: 1080px;
    background: v-bind('imageUrls.resultBg') center / cover no-repeat;
    position: absolute;
    top: 0;
    left: 0;
}

.result-logo {
    background: v-bind('imageUrls.logo');
    background-size: cover;
    width: 428px;
    height: 77px;
    position: absolute;
    left: 37px;
    top: 82px;
    z-index: 1;
}

.result-title {
    background: v-bind('imageUrls.resultTitle') center / cover no-repeat;
    width: 831px;
    height: 120px;
    position: absolute;
    left: 545px;
    top: 64px;
    z-index: 1;
}

.podium {
    background: v-bind('imageUrls.podium') no-repeat center;
    width: 1920px;
    height: 740px;
    position: absolute;
    bottom: 0;
    left: 0;
    z-index: 1;

    .img-vip {
        width: 969px;
        height: 238px;
        position: absolute;
        left: 480px;
        top: -60px;
        background: v-bind('imageUrls.vip') center / cover no-repeat;
    }

    .rank-no1 {
        position: relative;

        .avatar {
            width: 160px;
            height: 160px;
            border-radius: 80px;
            position: absolute;
            left: 884px;
            top: -7px;
        }

        .nickname {
            width: 220px;
            height: 52px;
            background: linear-gradient(0deg, #FFBF5A 0%, #FFE47A 100%);
            border: 1px solid #FFF9DC;
            text-align: center;
            line-height: 46px;
            position: absolute;
            left: 850px;
            top: 136px;
            z-index: 1;
            border-radius: 26px;
            font-size: 30px;
            color: #4B1A14;
        }
    }

    .rank-no2 {
        position: relative;

        .avatar {
            width: 144px;
            height: 144px;
            border-radius: 72px;
            position: absolute;
            left: 488px;
            top: 27px;
        }

        .nickname {
            width: 220px;
            height: 52px;
            background: linear-gradient(0deg, #AEA6A7 0%, #EAE4DF 100%);
            border: 1px solid white;
            color: #383636;
            text-align: center;
            line-height: 52px;
            position: absolute;
            left: 447px;
            top: 160px;
            z-index: 1;
            border-radius: 23px;
            font-size: 30px;
        }
    }

    .rank-no3 {
        position: relative;

        .avatar {
            width: 144px;
            height: 144px;
            border-radius: 72px;
            position: absolute;
            left: 1297px;
            top: 26px;
        }

        .nickname {
            width: 220px;
            height: 52px;
            background: linear-gradient(0deg, #F3AE76 0%, #F9CDA3 100%);
            color: #6F3A0E;
            text-align: center;
            line-height: 46px;
            position: absolute;
            left: 1255px;
            top: 160px;
            z-index: 1;
            border-radius: 26px;
            font-size: 30px;
            border: 1px solid #FEFEFD;
        }
    }
}

.rank-container {
    display: flex;
    align-items: center;
    width: 1570px;
    height: 115px;
    position: absolute;
    bottom: 263px;
    left: 200px;
    z-index: 2;

    > div {
        flex: 1;
        display: grid;
        width: 100px;
        height: 100%;

        .no-icon {
            background: v-bind('imageUrls.rankIcon') no-repeat center;
            width: 42px;
            height: 47px;
            position: absolute;
            text-align: center;
            line-height: 42px;
            color: #CC7F36;
            font-weight: bold;
            top: 50px;
        }

        .img-avatar-container {
            position: relative;
            margin: 0 auto;
            margin-top: 10px;
            width: 72px;
            height: 72px;
            border-radius: 36px;
            transform: scale(1.6);
            top: 50px;
        }

        .img-avatar-container::before {
            content: "";
            position: absolute;
            inset: 0;
            border-radius: inherit;
            background: v-bind('imageUrls.avatarAnimation') center / cover no-repeat;
            animation: avatar-rotate 10s linear infinite;
        }

        .img-avatar {
            position: relative;
            top: 6px;
            z-index: 1;
            margin: 0 auto;
            width: 60px;
            height: 60px;
            border-radius: 30px;
            background: v-bind('imageUrls.avatar') center / cover no-repeat;
        }

        .txt-nickname {
            color: #F9EBCB;
            font-size: 22px;
            text-align: center;
            position: absolute;
            top: 170px;
            margin-left: 68px;
        }
    }
}

.btn-next {
    position: absolute;
    bottom: 50px;
    left: 620px;
    width: 316px;
    height: 105px;
    cursor: pointer;
    background: v-bind('imageUrls.next') center / cover no-repeat;
    z-index: 2;
}

.btn-back {
    position: absolute;
    bottom: 50px;
    left: 1020px;
    width: 316px;
    height: 105px;
    cursor: pointer;
    background: v-bind('imageUrls.back') center / cover no-repeat;
    z-index: 2;
}

@keyframes avatar-rotate {
    0% {
        transform: rotate(0deg);
    }
    100% {
        transform: rotate(360deg);
    }
}
</style>
