<template>
    <view class="training-page">
        <view class="header">
            <view class="header-main">
                <text class="title">练一练</text>
                <text class="subtitle">器械动作跟练</text>
            </view>
            <view class="header-link" @click="goMetronome">
                🎵 节拍器
            </view>
        </view>

        <view class="equipment-tabs">
            <view
                v-for="eq in equipmentList"
                :key="eq"
                class="equipment-tab"
                :class="{ active: currentEquipment === eq }"
                @click="onSwitchEquipment(eq)"
            >
                {{ eq }}
            </view>
        </view>

        <scroll-view scroll-x class="exercise-scroll">
            <view class="exercise-list">
                <view
                    v-for="ex in filteredExercises"
                    :key="ex.id"
                    class="exercise-card"
                    :class="{ active: selectedId === ex.id }"
                    @click="onSelect(ex.id)"
                >
                    <text class="exercise-icon">{{ ex.icon }}</text>
                    <text class="exercise-name">{{ ex.name }}</text>
                </view>
            </view>
        </scroll-view>

        <view v-if="selected" class="exercise-detail">
            <exercise-anim
                :animation-type="selected.animationType"
                :bpm="bpm"
                :beats-per-rep="selected.beatsPerRep"
                :icon="selected.icon"
                :is-playing="metronomeIsPlaying"
            />

            <view class="beat-indicator">
                <view
                    v-for="i in 4"
                    :key="i"
                    class="beat-dot"
                    :class="{ active: ((beatIndex - 1) % 4) + 1 === i && metronomeIsPlaying }"
                />
            </view>

            <view class="meta-row">
                <text class="meta-label">{{ selected.description }}</text>
            </view>

            <view class="settings">
                <view class="setting-row">
                    <text class="setting-label">节奏</text>
                    <slider
                        :value="bpm"
                        :min="selected.bpmMin"
                        :max="selected.bpmMax"
                        :step="2"
                        block-size="24"
                        active-color="#22c55e"
                        @change="onBpmChange"
                    />
                    <text class="setting-value">{{ bpm }} BPM</text>
                </view>

                <view class="setting-row inline">
                    <view class="inline-item">
                        <text class="setting-label">组数</text>
                        <view class="stepper">
                            <text class="step-btn" @click="adjust('sets', -1)">-</text>
                            <text class="step-val">{{ sets }}</text>
                            <text class="step-btn" @click="adjust('sets', 1)">+</text>
                        </view>
                    </view>
                    <view class="inline-item">
                        <text class="setting-label">次数</text>
                        <view class="stepper">
                            <text class="step-btn" @click="adjust('reps', -1)">-</text>
                            <text class="step-val">{{ reps }}</text>
                            <text class="step-btn" @click="adjust('reps', 1)">+</text>
                        </view>
                    </view>
                    <view class="inline-item">
                        <text class="setting-label">休息(秒)</text>
                        <view class="stepper">
                            <text class="step-btn" @click="adjust('rest', -15)">-</text>
                            <text class="step-val">{{ restSec }}</text>
                            <text class="step-btn" @click="adjust('rest', 15)">+</text>
                        </view>
                    </view>
                </view>
            </view>

            <view v-if="!isTraining && !isResting && !isDone" class="action-row">
                <button class="btn-primary" @click="onStart">开始训练</button>
            </view>

            <view v-if="isTraining" class="status-card training">
                <text class="status-title">训练中</text>
                <text class="status-line">第 {{ currentSet }} / {{ totalSets }} 组</text>
                <text class="status-line big">{{ currentRep }} / {{ totalReps }}</text>
                <view class="action-row">
                    <button class="btn-secondary" @click="onStop">停止</button>
                </view>
            </view>

            <view v-if="isResting" class="status-card resting">
                <text class="status-title">休息中</text>
                <text class="status-line big">{{ restRemainingSec }}s</text>
                <view class="action-row">
                    <button class="btn-secondary" @click="onSkipRest">跳过休息</button>
                    <button class="btn-text" @click="onStop">结束训练</button>
                </view>
            </view>

            <view v-if="isDone" class="status-card done">
                <text class="status-title">训练完成 🎉</text>
                <text class="status-line">共 {{ totalSets }} 组 × {{ totalReps }} 次</text>
                <view class="action-row">
                    <button class="btn-primary" @click="onStart">再来一次</button>
                </view>
            </view>

            <view class="tips-card">
                <text class="tips-title">动作要领</text>
                <text v-for="(tip, i) in selected.tips" :key="i" class="tips-item">
                    • {{ tip }}
                </text>
                <text v-if="selected.contraindication" class="tips-warn">
                    ⚠ {{ selected.contraindication }}
                </text>
            </view>
        </view>
    </view>
</template>

<script setup lang="ts">
import { ref, computed, watch, onUnmounted } from 'vue'
import { onShow, onHide } from '@dcloudio/uni-app'
import ExerciseAnim from './components/exercise-anim.vue'
import { EXERCISE_PRESETS, getPresetById } from './exercises'
import type { ExercisePreset } from './exercises'
import { useMetronome } from '@/hooks/useMetronome'
import { useTrainingSession } from '@/hooks/useTrainingSession'
import { useVoiceCoach } from '@/hooks/useVoiceCoach'
import { useTrainingBgm } from '@/hooks/useTrainingBgm'

const equipmentList = ['哑铃', '握力环', '健身环', '徒手'] as const
type Equipment = (typeof equipmentList)[number]

const currentEquipment = ref<Equipment>('哑铃')
const selectedId = ref<string>(EXERCISE_PRESETS[0].id)

const filteredExercises = computed(() =>
    EXERCISE_PRESETS.filter((e) => e.equipment === currentEquipment.value),
)

const selected = computed<ExercisePreset | undefined>(() =>
    getPresetById(selectedId.value),
)

const bpm = ref<number>(60)
const sets = ref<number>(3)
const reps = ref<number>(12)
const restSec = ref<number>(60)

watch(
    selected,
    (val) => {
        if (!val) return
        bpm.value = val.defaultBpm
        sets.value = val.defaultSets
        reps.value = val.defaultReps
        restSec.value = val.defaultRestSec
    },
    { immediate: true },
)

const voice = useVoiceCoach()
const bgm = useTrainingBgm()

const session = useTrainingSession()
const {
    currentSet,
    currentRep,
    restRemainingSec,
    totalReps,
    totalSets,
    isTraining,
    isResting,
    isDone,
} = session

const metronome = useMetronome({
    initialBpm: bpm.value,
    onBeat: () => session.onBeat(),
})
const { beatIndex, isPlaying: metronomeIsPlaying } = metronome

watch(bpm, (v) => metronome.setBpm(v))

const onSwitchEquipment = (eq: Equipment) => {
    if (isTraining.value || isResting.value) return
    currentEquipment.value = eq
    const first = EXERCISE_PRESETS.find((e) => e.equipment === eq)
    if (first) selectedId.value = first.id
}

const onSelect = (id: string) => {
    if (isTraining.value || isResting.value) return
    selectedId.value = id
}

const onBpmChange = (e: any) => {
    const v = e.detail?.value ?? e
    bpm.value = Number(v)
}

const adjust = (key: 'sets' | 'reps' | 'rest', delta: number) => {
    if (isTraining.value || isResting.value) return
    if (key === 'sets') sets.value = Math.max(1, Math.min(10, sets.value + delta))
    if (key === 'reps') reps.value = Math.max(1, Math.min(50, reps.value + delta))
    if (key === 'rest') restSec.value = Math.max(0, Math.min(300, restSec.value + delta))
}

const onStart = () => {
    if (!selected.value) return
    uni.setKeepScreenOn({ keepScreenOn: true })

    voice.speakPrompt('start')

    session.start({
        sets: sets.value,
        reps: reps.value,
        restSec: restSec.value,
        beatsPerRep: selected.value.beatsPerRep,
        onRepComplete: (rep, total) => {
            if (rep <= 30) voice.speakNumber(rep)
            if (rep === total - 1) voice.speakPrompt('last-rep')
        },
        onSetComplete: (set, total) => {
            if (set < total) voice.speakPrompt('keep-it-up')
        },
        onEnterRest: () => {
            metronome.stop()
            voice.speakPrompt('rest')
            bgm.switchTo('resting')
        },
        onExitRest: () => {
            voice.speakPrompt('next-set')
            bgm.switchTo('training')
            metronome.start()
        },
        onDone: () => {
            metronome.stop()
            bgm.switchTo('none')
            voice.speakPrompt('good-job')
            uni.setKeepScreenOn({ keepScreenOn: false })
        },
    })

    bgm.switchTo('training')
    metronome.start()
}

const onStop = () => {
    metronome.stop()
    session.stop()
    bgm.switchTo('none')
    uni.setKeepScreenOn({ keepScreenOn: false })
}

const onSkipRest = () => {
    session.skipRest()
}

const goMetronome = () => {
    uni.navigateTo({ url: '/pages/training/metronome' })
}

onHide(() => {
    if (isTraining.value || isResting.value) {
        onStop()
    }
})

onUnmounted(() => {
    uni.setKeepScreenOn({ keepScreenOn: false })
})
</script>

<style lang="scss" scoped>
.training-page {
    min-height: 100vh;
    background: #f9fafb;
    padding: 32rpx 24rpx 80rpx;
}

.header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 24rpx;

    .header-main {
        display: flex;
        flex-direction: column;
        align-items: flex-start;
    }

    .title {
        font-size: 44rpx;
        font-weight: 700;
        color: #111827;
    }
    .subtitle {
        font-size: 26rpx;
        color: #6b7280;
        margin-top: 6rpx;
    }

    .header-link {
        padding: 12rpx 24rpx;
        background: #f3f4f6;
        border-radius: 24rpx;
        font-size: 24rpx;
        color: #4b5563;

        &:active {
            background: #e5e7eb;
        }
    }
}

.equipment-tabs {
    display: flex;
    gap: 16rpx;
    margin-bottom: 24rpx;
    overflow-x: auto;

    .equipment-tab {
        flex-shrink: 0;
        padding: 14rpx 32rpx;
        background: #fff;
        border-radius: 32rpx;
        font-size: 28rpx;
        color: #4b5563;
        border: 2rpx solid transparent;

        &.active {
            background: #22c55e;
            color: #fff;
            border-color: #22c55e;
        }
    }
}

.exercise-scroll {
    width: 100%;
    margin-bottom: 24rpx;
}

.exercise-list {
    display: flex;
    gap: 16rpx;
    padding-right: 16rpx;
}

.exercise-card {
    flex-shrink: 0;
    width: 160rpx;
    padding: 20rpx 12rpx;
    background: #fff;
    border-radius: 16rpx;
    text-align: center;
    border: 2rpx solid transparent;

    &.active {
        border-color: #22c55e;
        background: #f0fdf4;
    }

    .exercise-icon {
        display: block;
        font-size: 56rpx;
        margin-bottom: 8rpx;
    }
    .exercise-name {
        font-size: 24rpx;
        color: #374151;
    }
}

.exercise-detail {
    display: flex;
    flex-direction: column;
    gap: 24rpx;
}

.beat-indicator {
    display: flex;
    justify-content: center;
    gap: 16rpx;
    padding: 8rpx 0;

    .beat-dot {
        width: 16rpx;
        height: 16rpx;
        border-radius: 50%;
        background: #d1d5db;
        transition: transform 0.15s, background 0.15s;

        &.active {
            background: #22c55e;
            transform: scale(1.6);
        }
    }
}

.meta-row {
    .meta-label {
        font-size: 26rpx;
        color: #6b7280;
        text-align: center;
        display: block;
    }
}

.settings {
    background: #fff;
    border-radius: 20rpx;
    padding: 24rpx;
    display: flex;
    flex-direction: column;
    gap: 24rpx;
}

.setting-row {
    display: flex;
    align-items: center;
    gap: 16rpx;

    .setting-label {
        font-size: 26rpx;
        color: #4b5563;
        min-width: 80rpx;
    }
    .setting-value {
        font-size: 26rpx;
        color: #22c55e;
        font-weight: 600;
        min-width: 120rpx;
        text-align: right;
    }
    slider {
        flex: 1;
    }

    &.inline {
        justify-content: space-between;
        gap: 8rpx;
    }
}

.inline-item {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8rpx;
    flex: 1;
}

.stepper {
    display: flex;
    align-items: center;
    gap: 12rpx;

    .step-btn {
        width: 48rpx;
        height: 48rpx;
        line-height: 48rpx;
        text-align: center;
        background: #f3f4f6;
        border-radius: 24rpx;
        font-size: 32rpx;
        color: #4b5563;
    }
    .step-val {
        font-size: 30rpx;
        font-weight: 600;
        color: #111827;
        min-width: 56rpx;
        text-align: center;
    }
}

.action-row {
    display: flex;
    gap: 16rpx;
    justify-content: center;

    button {
        flex: 1;
        max-width: 320rpx;
    }
}

.btn-primary {
    background: #22c55e;
    color: #fff;
    border-radius: 999rpx;
    font-size: 30rpx;
    height: 88rpx;
    line-height: 88rpx;
    border: none;
}

.btn-secondary {
    background: #fff;
    color: #22c55e;
    border: 2rpx solid #22c55e;
    border-radius: 999rpx;
    font-size: 28rpx;
    height: 80rpx;
    line-height: 76rpx;
}

.btn-text {
    background: transparent;
    color: #ef4444;
    font-size: 26rpx;
    height: 80rpx;
    line-height: 80rpx;
    border: none;
}

.status-card {
    background: #fff;
    border-radius: 20rpx;
    padding: 32rpx 24rpx;
    text-align: center;
    display: flex;
    flex-direction: column;
    gap: 12rpx;
    align-items: center;

    &.training {
        background: linear-gradient(135deg, #f0fdf4, #ecfeff);
    }
    &.resting {
        background: linear-gradient(135deg, #fef3c7, #fef9c3);
    }
    &.done {
        background: linear-gradient(135deg, #dbeafe, #ede9fe);
    }

    .status-title {
        font-size: 30rpx;
        color: #4b5563;
        font-weight: 600;
    }
    .status-line {
        font-size: 28rpx;
        color: #6b7280;
        &.big {
            font-size: 64rpx;
            color: #111827;
            font-weight: 700;
        }
    }
}

.tips-card {
    background: #fff;
    border-radius: 20rpx;
    padding: 24rpx;
    display: flex;
    flex-direction: column;
    gap: 8rpx;

    .tips-title {
        font-size: 28rpx;
        font-weight: 600;
        color: #111827;
        margin-bottom: 8rpx;
    }
    .tips-item {
        font-size: 26rpx;
        color: #4b5563;
        line-height: 1.6;
    }
    .tips-warn {
        font-size: 26rpx;
        color: #ef4444;
        margin-top: 12rpx;
        line-height: 1.6;
    }
}
</style>
