<script setup lang="ts">
import { onBeforeUnmount, onMounted, ref } from 'vue'
import { assetUrl } from '@/commons/assets'

const shakeSound = assetUrl('game4/yaoyiyao.mp3')

const props = defineProps<{
    imageUrls: Record<string, string>
    countdownInterval: number
    isDivDescVisible: boolean
    tick: number
    rank: number
    currentHorse: string
    currentYaoyiyao: string
}>()

const emit = defineEmits<{
    touch: []
}>()

// ========== iOS 设备检测 ==========
const isIOS = typeof (DeviceMotionEvent as any).requestPermission === 'function'
const showIOSHint = ref(isIOS)

// ========== 摇一摇 ==========
const shakeCooldown = 300
let lastShakeTime = 0

let lastPosition = {
    x: 0,
    y: 0,
    z: 0,
    time: Date.now(),
}

// 是否正在摇晃（用于停止检测）
let wasShaking = false

let audioContext: AudioContext | null = null
let shakeAudioBuffer: AudioBuffer | null = null

// iOS 13+/iPadOS 需要主动请求 DeviceMotion 权限
let motionPermissionGranted = false

// 摇一摇图片抖动动画状态
const isYaoyiyaoShaking = ref(false)
let yaoyiyaoShakeTimer: ReturnType<typeof setTimeout> | null = null

const requestMotionPermission = async (): Promise<boolean> => {
    // 检查是否需要权限请求（iOS 12.2+）
    if (typeof (DeviceMotionEvent as any).requestPermission === 'function') {
        try {
            const state = await (DeviceMotionEvent as any).requestPermission()
            if (state === 'granted') {
                console.log('[摇一摇] iOS DeviceMotion 权限已授予')
                motionPermissionGranted = true
                // 权限拿到后再注册监听
                window.addEventListener('devicemotion', handleDeviceMotion)
                return true
            }
            console.warn('[摇一摇] iOS DeviceMotion 权限被拒绝:', state)
            return false
        } catch (err) {
            console.error('[摇一摇] iOS 权限请求失败:', err)
            return false
        }
    }
    // Android / 旧版 iOS：无需额外权限
    motionPermissionGranted = true
    return true
}

const initAudio = async () => {
    try {
        audioContext = new (window.AudioContext || (window as any).webkitAudioContext)()
        const response = await fetch(shakeSound)
        const arrayBuffer = await response.arrayBuffer()
        shakeAudioBuffer = await audioContext.decodeAudioData(arrayBuffer)
    } catch (error) {
        console.error('[摇一摇] 音频初始化失败:', error)
    }
}

const playShakeSound = () => {
    if (!audioContext || !shakeAudioBuffer) return
    if (audioContext.state === 'suspended') {
        audioContext.resume()
    }
    const source = audioContext.createBufferSource()
    source.buffer = shakeAudioBuffer
    source.connect(audioContext.destination)
    source.start(0)
}

const handleDeviceMotion = (ev: DeviceMotionEvent) => {
    const nowTime = Date.now()
    const motion = ev.accelerationIncludingGravity
    if (!motion || motion.x === null) return

    const range = 50

    if (nowTime - lastPosition.time > 100) {
        const nowPosition = {
            x: motion.x!,
            y: motion.y!,
            z: motion.z!,
        }

        // 两次摇晃的差值（位移法）
        const dis =
            Math.abs(nowPosition.x - lastPosition.x) +
            Math.abs(nowPosition.y - lastPosition.y) +
            Math.abs(nowPosition.z - lastPosition.z)

        if (dis > range) {
            wasShaking = true

            const now = Date.now()
            if (now - lastShakeTime < shakeCooldown) return
            lastShakeTime = now

            // 摇一摇图片抖动动画
            isYaoyiyaoShaking.value = true
            if (yaoyiyaoShakeTimer) clearTimeout(yaoyiyaoShakeTimer)
            yaoyiyaoShakeTimer = setTimeout(() => {
                isYaoyiyaoShaking.value = false
            }, 320)

            playShakeSound()

            // 摇晃时打印日志：输出将要通过 websocket 提交的数据
            console.log('[摇一摇] 检测到摇晃，即将提交数据:', {
                type: 'submit_score',
                data: { score: props.tick + 1 },
            })

            emit('touch')
        }

        // 用户停止摇晃（停止事件不需要处理）
        if (dis < range && wasShaking) {
            wasShaking = false
        }

        lastPosition.x = nowPosition.x
        lastPosition.y = nowPosition.y
        lastPosition.z = nowPosition.z
        lastPosition.time = nowTime
    }
}

// ========== 生命周期 ==========

onMounted(async () => {
    try {
        await initAudio()
    } catch (error) {
        console.error('初始化失败:', error)
    }

    // 非 iOS 设备直接注册监听；iOS 需等用户点击后通过 requestMotionPermission 注册
    if (typeof (DeviceMotionEvent as any).requestPermission !== 'function') {
        window.addEventListener('devicemotion', handleDeviceMotion)
        motionPermissionGranted = true
        console.log('[摇一摇] DeviceMotion 监听已启动（Android/旧版iOS）')
    } else {
        console.log('[摇一摇] 等待用户点击以请求 iOS DeviceMotion 权限…')
    }
})

onBeforeUnmount(() => {
    window.removeEventListener('devicemotion', handleDeviceMotion)
    if (audioContext) {
        audioContext.close()
    }
    if (yaoyiyaoShakeTimer) {
        clearTimeout(yaoyiyaoShakeTimer)
    }
})

// 点击马触发：iOS 先请求权限（不触发得分）
const onTapHorse = async () => {
    if (!motionPermissionGranted) {
        await requestMotionPermission()
        showIOSHint.value = false
    }
}
</script>

<template>
    <div class="h5-page game-stage">
        <Transition name="div-desc-slide" appear>
            <div v-if="isDivDescVisible" class="div-desc">
                <span class="desc-clock" aria-hidden="true"></span>
                <span class="desc-time">{{ countdownInterval }}</span>
            </div>
        </Transition>
        <div class="img-logo"></div>
        <div class="img-gift"></div>
        <!-- <div class="img-time"></div> -->
        <div class="play-content">
            <div>当前得分</div>
            <div>{{ tick }}</div>
            <div>当前排名: &nbsp;第&nbsp;<label>{{ rank }}</label>&nbsp;名</div>
        </div>
        <!-- iOS 权限提示蒙层 -->
        <Transition name="ios-hint-fade">
            <div v-if="showIOSHint" class="ios-hint-overlay" @click="onTapHorse">
                <div class="ios-hint-content">
                    <div class="ios-hint-title">👇点击下方赛马</div>
                    <div class="ios-hint-desc">启用摇一摇功能开始游戏</div>
                    <div class="ios-hint-arrow">⬇</div>
                </div>
            </div>
        </Transition>
        <!-- <div class="bg-bottom"></div> -->
        <div class="bg-yaoyiyao" :class="{ 'is-shaking': isYaoyiyaoShaking }" :style="{ background: `${currentYaoyiyao} center/cover` }"></div>
        <div class="play-horse" :class="{ 'horse-clickable': showIOSHint }" :style="{ background: `${currentHorse} center/cover` }" @click="onTapHorse"></div>
    </div>
</template>

<style scoped>
.game-stage {
    position: absolute;
    width: 750px;
    height: 1624px;
    padding: 0;
}

.div-desc {
    position: absolute;
    top: 150px;
    left: var(--stage-viewport-left, 0);
    z-index: 2;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 24px;
    width: 180px;
    height: 80px;
    border-radius: 0 56px 56px 0;
    background: rgba(40, 12, 8, 0.48);
    color: #fff;


    .desc-clock {
        position: absolute;
        left: 20px;
        width: 38px;
        height: 44px;
        border-radius: 50%;
        background: v-bind('imageUrls.clock') center/cover;
    }

    .desc-time {
        position: absolute;
        right: 40px;
        color: white;
        font-size: 35pt;
        line-height: 1;
    }
}

.div-desc-slide-enter-active {
    transition:
        transform 360ms ease-out 220ms,
        opacity 360ms ease-out 220ms;
}

.div-desc-slide-leave-active {
    transition:
        transform 260ms ease-in,
        opacity 260ms ease-in;
}

.div-desc-slide-enter-from,
.div-desc-slide-leave-to {
    opacity: 0;
    transform: translateX(-110%);
}

.div-desc-slide-enter-to,
.div-desc-slide-leave-from {
    opacity: 1;
    transform: translateX(0);
}

.bg-bottom {
    position: absolute;
    bottom: 0;
    left: var(--stage-viewport-left, 0);
    width: var(--stage-viewport-width, 750px);
    height: 479px;
    background: v-bind('imageUrls.bg2') center/cover;
    opacity: 0.6;
}

.img-logo {
    position: absolute;
    top: 66px;
    left: 50%;
    width: 428px;
    height: 77px;
    background: v-bind('imageUrls.logo') center/cover;
    transform: translateX(-50%);
}
.img-gift {
    position: absolute;
    top: 421px;
    right: -10px;
    right: -10%;
    width: 234.1px;
    height: 142.21px;
    background: v-bind('imageUrls.gift') center/cover;
    /* transform: scale(0.8); */
}
/* .img-time {
    position: absolute;
    top: 66px;
    left: 50%;
    width: 428px;
    height: 77px;
    background: v-bind('imageUrls.time') center/cover;
    transform: translateX(-50%);
} */

.play-content {
    position: absolute;
    top: 250px;
    left:0;
    right: 0;
    margin: 0 auto;
    width: 556px;
    padding: 30px 0;
    border-radius: 25px;
    background: rgba(40, 12, 8, 0.52);
    color: white;
    font-size: 28pt;
    text-align: center;
}

.play-content>div:nth-child(2) {
    display: inline-block;
    margin: 10px 0;
    background: linear-gradient(180deg, #FFE68D 0%, #FAD500 100%);
    background-clip: text;
    color: transparent;
    font-size: 48pt;
    font-weight: bold;
    transform: scaleY(1.2);
    transform-origin: center;
    -webkit-background-clip: text;
}

.play-content>div:nth-child(3) {
    position: relative;
    top: -10px;
}

.play-content>div:nth-child(3) label {
    color: white;
    font-size: 42pt;
}

.bg-yaoyiyao {
    position: absolute;
    top: 698px;
    left: 50%;
    width: 514.51px;
    height: 229px;
    transform: translateX(-50%);
    transition: transform 0.08s ease-out;
}

/* 摇一摇图片抖动动画 */
.bg-yaoyiyao.is-shaking {
    animation: yaoyiyao-shake 0.32s ease-in-out;
}

@keyframes yaoyiyao-shake {
    0%   { transform: translateX(-50%) rotate(0deg); }
    15%  { transform: translateX(-50%) rotate(-8deg); }
    30%  { transform: translateX(-50%) rotate(8deg); }
    45%  { transform: translateX(-50%) rotate(-6deg); }
    60%  { transform: translateX(-50%) rotate(6deg); }
    75%  { transform: translateX(-50%) rotate(-3deg); }
    90%  { transform: translateX(-50%) rotate(3deg); }
    100% { transform: translateX(-50%) rotate(0deg); }
}

.play-horse {
    position: absolute;
    bottom: 164px;
    left: 50%;
    width: 597px;
    height: 679px;
    transform: translateX(-50%);
}

/* 马匹点击引导动画 - 脉冲呼吸效果 */
.horse-clickable {
    animation: horse-pulse 1.2s ease-in-out infinite;
}

@keyframes horse-pulse {
    0%, 100% { filter: brightness(1) drop-shadow(0 0 8px rgba(255, 215, 0, 0)); }
    50%      { filter: brightness(1.12) drop-shadow(0 0 24px rgba(255, 215, 0, 0.6)); }
}

/* ===== iOS 权限提示蒙层 ===== */
.ios-hint-overlay {
    position: absolute;
    top: 0;
    bottom: 0;
    left: var(--stage-viewport-left, 0);
    width: var(--stage-viewport-width, 750px);
    z-index: 10;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(0, 0, 0, 0.55);
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}
.ios-hint-content {
    text-align: center;
    color: #fff;
    animation: ios-hint-bounce 1.6s ease-in-out infinite;
}
.ios-hint-title {
    font-size: 36pt;
    font-weight: bold;
    margin-bottom: 16px;
    text-shadow: 0 2px 8px rgba(0, 0, 0, 0.5);
}
.ios-hint-desc {
    font-size: 22pt;
    opacity: 0.85;
    margin-bottom: 20px;
    text-shadow: 0 1px 4px rgba(0, 0, 0, 0.5);
}
.ios-hint-arrow {
    font-size: 40pt;
    animation: ios-arrow-bounce 0.8s ease-in-out infinite alternate;
}
@keyframes ios-hint-bounce {
    0%, 100% { transform: translateY(0); }
    50%      { transform: translateY(-12px); }
}
@keyframes ios-arrow-bounce {
    from { transform: translateY(0); opacity: 1; }
    to   { transform: translateY(16px); opacity: 0.3; }
}

.ios-hint-fade-enter-active {
    transition: opacity 0.4s ease;
}
.ios-hint-fade-leave-active {
    transition: opacity 0.3s ease;
}
.ios-hint-fade-enter-from,
.ios-hint-fade-leave-to {
    opacity: 0;
}

</style>
