import { ref, computed, onUnmounted } from 'vue' export type SessionPhase = 'idle' | 'training' | 'resting' | 'done' export interface TrainingSessionConfig { sets: number reps: number restSec: number beatsPerRep?: number onRepComplete?: (currentRep: number, totalReps: number) => void onSetComplete?: (currentSet: number, totalSets: number) => void onEnterRest?: (restSec: number) => void onExitRest?: () => void onDone?: () => void onCountdownTick?: (remainingSec: number) => void } export function useTrainingSession() { const phase = ref('idle') const currentSet = ref(0) const currentRep = ref(0) const restRemainingSec = ref(0) const beatCounter = ref(0) let config: TrainingSessionConfig | null = null let restTimer: ReturnType | null = null const totalReps = computed(() => config?.reps ?? 0) const totalSets = computed(() => config?.sets ?? 0) const beatsPerRep = computed(() => config?.beatsPerRep ?? 2) const isTraining = computed(() => phase.value === 'training') const isResting = computed(() => phase.value === 'resting') const isDone = computed(() => phase.value === 'done') const start = (cfg: TrainingSessionConfig) => { config = cfg phase.value = 'training' currentSet.value = 1 currentRep.value = 0 beatCounter.value = 0 restRemainingSec.value = 0 } const onBeat = () => { if (phase.value !== 'training' || !config) return beatCounter.value++ if (beatCounter.value % beatsPerRep.value !== 0) return currentRep.value++ config.onRepComplete?.(currentRep.value, totalReps.value) if (currentRep.value >= totalReps.value) { config.onSetComplete?.(currentSet.value, totalSets.value) if (currentSet.value >= totalSets.value) { phase.value = 'done' config.onDone?.() return } enterRest() } } const enterRest = () => { if (!config) return phase.value = 'resting' restRemainingSec.value = config.restSec config.onEnterRest?.(config.restSec) restTimer = setInterval(() => { restRemainingSec.value-- config?.onCountdownTick?.(restRemainingSec.value) if (restRemainingSec.value <= 0) { exitRest() } }, 1000) } const exitRest = () => { if (restTimer) { clearInterval(restTimer) restTimer = null } if (!config) return currentSet.value++ currentRep.value = 0 beatCounter.value = 0 phase.value = 'training' config.onExitRest?.() } const skipRest = () => { if (phase.value !== 'resting') return exitRest() } const stop = () => { if (restTimer) { clearInterval(restTimer) restTimer = null } phase.value = 'idle' currentSet.value = 0 currentRep.value = 0 beatCounter.value = 0 restRemainingSec.value = 0 } onUnmounted(() => { if (restTimer) clearInterval(restTimer) }) return { phase, currentSet, currentRep, restRemainingSec, totalReps, totalSets, isTraining, isResting, isDone, start, stop, skipRest, onBeat, } }