document.addEventListener('DOMContentLoaded', async () => {
    
    // --- AUDIO DATA (INLINED BY BUILD SCRIPT) ---
    // __SOUND_DATA_PLACEHOLDER__

    const app = {
        // --- STATE ---
        workouts: [],
        db: null,
        currentView: 'home',
        currentWorkoutId: null,
        currentExerciseIndex: 0,
        runnerInterval: null,
        wakeLock: null,
        userHasInteracted: false,
        timerState: 'idle',
        timeRemainingOnPause: 0,
        currentRepOnPause: 1,

        // Web Audio API state
        audioContext: null, soundBuffers: {}, soundsLoaded: false, audioLoading: false,
        runnerViewEl: null,

        // --- INITIALIZATION & CORE ---
        async init() {
            await this.initDB();
            await this.loadWorkouts();
            this.attachEventListeners();
            this.registerServiceWorker();
            this.render();
        },
        
        registerServiceWorker() {
            if ('serviceWorker' in navigator) {
                navigator.serviceWorker.register('/service-worker.js');
            }
        },
        
        async initDB() {
            this.db = await idb.openDB('WorkItDB', 1, {
                upgrade(db) {
                    db.createObjectStore('workouts', { keyPath: 'id' });
                },
            });
            console.log("Database initialized.");
        },
        
        async loadWorkouts() {
            const oldData = localStorage.getItem('workouts');
            if (oldData) {
                console.log("Found old data in localStorage. Migrating to IndexedDB...");
                try {
                    const oldWorkouts = JSON.parse(oldData);
                    if (Array.isArray(oldWorkouts)) {
                        const tx = this.db.transaction('workouts', 'readwrite');
                        await Promise.all(oldWorkouts.map(workout => tx.store.put(workout)));
                        await tx.done;
                        localStorage.removeItem('workouts');
                        console.log("Migration successful.");
                    }
                } catch (e) {
                    console.error("Failed to parse or migrate old data:", e);
                }
            }
            this.workouts = await this.db.getAll('workouts');
        },
        
        async saveWorkouts() {
            const tx = this.db.transaction('workouts', 'readwrite');
            await tx.store.clear();
            await Promise.all(this.workouts.map(workout => tx.store.put(workout)));
            await tx.done;
        },

        async acquireWakeLock() {
            if ('wakeLock' in navigator) try { this.wakeLock = await navigator.wakeLock.request('screen'); } catch (e) {}
        },
        
        async releaseWakeLock() {
            if (this.wakeLock) {
                await this.wakeLock.release();
                this.wakeLock = null;
            }
        },
        
        async initAudio(triggerElement) {
            if (this.audioLoading || this.soundsLoaded) return;
            this.audioLoading = true;
            if (triggerElement) { triggerElement.disabled = true; triggerElement.textContent = 'Loading...'; }
            if (!this.audioContext) this.audioContext = new (window.AudioContext || window.webkitAudioContext)();
            await this.loadSounds();
            this.audioLoading = false;
            if (triggerElement) {
                triggerElement.disabled = false;
                if (triggerElement.dataset.action === 'start') { triggerElement.innerHTML = '&#9654;'; } 
                else { triggerElement.textContent = 'Start Exercise'; }
            }
        },

        async loadSounds() {
            if (typeof soundData === 'undefined') { console.error("Sound data not defined."); return; }
            const soundNames = Object.keys(soundData);
            const loadPromises = soundNames.map(async (name) => {
                try {
                    const response = await fetch(soundData[name]);
                    const arrayBuffer = await response.arrayBuffer();
                    const audioBuffer = await this.audioContext.decodeAudioData(arrayBuffer);
                    this.soundBuffers[name] = audioBuffer;
                } catch (e) { console.error(`Failed to decode sound: ${name}`, e); }
            });
            await Promise.all(loadPromises);
            this.soundsLoaded = true;
            console.log("All inlined sounds decoded.");
        },

        playSound(name) {
            if (!this.audioContext || !this.soundBuffers[name]) return;
            if (this.audioContext.state === 'suspended') this.audioContext.resume();
            const source = this.audioContext.createBufferSource();
            source.buffer = this.soundBuffers[name];
            source.connect(this.audioContext.destination);
            source.start(0);
        },

        render() {
            const container = document.getElementById('app-container');
            container.innerHTML = '';
            if (this.runnerViewEl) { this.runnerViewEl.remove(); this.runnerViewEl = null; }
            if (this.currentView === 'home') this.renderHome(container);
            if (this.currentView === 'editor') this.renderEditor(container);
        },

        renderHome(container) {
            let content = `<h1>My Workouts</h1>`;
            if (Array.isArray(this.workouts)) {
                this.workouts.forEach(workout => {
                    content += `
                        <div class="workout-list-item" data-id="${workout.id}">
                            <h3>${workout.name}</h3>
                            <div class="workout-actions">
                                <button data-action="edit" title="Edit">Edit</button>
                                <button data-action="start" title="Start Workout">&#9654;</button>
                            </div>
                        </div>
                    `;
                });
            }
            content += `<button class="button" data-action="new-workout">Create New Workout</button>`;
            container.innerHTML = content;
        },

        renderEditor(container) {
            const workout = this.workouts.find(w => w.id === this.currentWorkoutId) ||
                            { id: Date.now(), name: 'New Workout', exercises: [] };
            let exercisesHtml = '';
            workout.exercises.forEach((ex, index) => {
                const showDelay = ex.reps && ex.time;
                exercisesHtml += `
                    <div class="exercise-card" data-index="${index}">
                        <div class="exercise-header">
                            <h4>${ex.name || 'New Exercise'}</h4>
                            <div class="exercise-controls">
                                <button data-action="move-up" title="Move Up">&#8593;</button>
                                <button data-action="move-down" title="Move Down">&#8595;</button>
                                <button data-action="delete-exercise" class="delete" title="Delete Exercise">&times;</button>
                            </div>
                        </div>
                        <div class="exercise-details"> <p>${ex.description || ''}</p> <p><strong>Reps:</strong> ${ex.reps || 'N/A'} | <strong>Time:</strong> ${ex.time || 'N/A'}s | <strong>Delay:</strong> ${ex.delay || 'N/A'}s</p> </div>
                        <div class="input-group"> <label>Name</label> <input type="text" data-field="name" value="${ex.name || ''}"> </div>
                        <div class="input-group"> <label>Description</label> <textarea data-field="description">${ex.description || ''}</textarea> </div>
                        <div class="input-group"> <label>Reps</label> <input type="number" data-field="reps" value="${ex.reps || ''}"> </div>
                        <div class="input-group"> <label>Time (seconds)</label> <input type="number" data-field="time" value="${ex.time || ''}"> </div>
                        <div class="input-group delay-group" style="display: ${showDelay ? 'block' : 'none'};"> <label>Delay between reps (seconds)</label> <input type="number" data-field="delay" value="${ex.delay || ''}"> </div>
                    </div>
                `;
            });
            const content = `
                <div class="input-group"> <label for="workout-name">Workout Name</label> <input type="text" id="workout-name" value="${workout.name}"> </div>
                <h2>Exercises</h2> <div id="exercise-list">${exercisesHtml}</div>
                <button class="button secondary" data-action="add-exercise">Add Exercise</button>
                <button class="button" data-action="save-workout">Save Workout</button>
                <div class="editor-actions">
                    <button class="button secondary" data-action="clone-workout">Clone Workout</button>
                    <button class="button danger" data-action="delete-workout">Delete Workout</button>
                </div>
                <button class="button secondary" data-action="back-home" style="margin-top: 2rem;">Back to Home</button>
            `;
            container.innerHTML = content;
        },
        
        attachEventListeners() {
            document.body.addEventListener('click', async (e) => {
                const target = e.target.closest('[data-action]');
                if (!target) return;
                
                if (this.audioContext && this.audioContext.state === 'suspended') await this.audioContext.resume();
                const action = target.dataset.action;
                if (!this.soundsLoaded && (action === 'start' || action === 'get-ready')) await this.initAudio(target);
                
                const workoutEl = target.closest('.workout-list-item');
                const workoutId = workoutEl ? parseInt(workoutEl.dataset.id) : this.currentWorkoutId;
                
                const actions = {
                    'new-workout': () => this.newWorkout(),
                    'edit': () => this.editWorkout(workoutId),
                    'delete': () => this.deleteWorkout(workoutId),
                    'clone': () => this.cloneWorkout(workoutId),
                    'start': () => this.startRunner(workoutId),
                    'save-workout': () => this.saveWorkoutFromEditor(),
                    'back-home': () => this.goHome(),
                    'add-exercise': () => this.addExercise(),
                    'delete-exercise': () => this.deleteExercise(parseInt(target.closest('.exercise-card').dataset.index)),
                    'move-up': () => this.moveExercise(parseInt(target.closest('.exercise-card').dataset.index), -1),
                    'move-down': () => this.moveExercise(parseInt(target.closest('.exercise-card').dataset.index), 1),
                    'stop-runner': () => this.stopRunner(),
                    'next-exercise': () => this.changeExercise(1),
                    'prev-exercise': () => this.changeExercise(-1),
                    'get-ready': () => this.runGetReadyCountdown(),
                    'pause-timer': () => this.pauseTimer(),
                    'resume-timer': () => this.resumeTimer(),
                    'reset-timer': () => this.resetTimer(),
                    'clone-workout': () => this.cloneWorkout(workoutId),
                    'delete-workout': () => this.deleteWorkout(workoutId),
                    'finish-workout': () => this.renderCompletionScreen(),
                };
                if (actions[action]) await actions[action]();
            });
            
            document.body.addEventListener('input', e => {
                if (this.currentView !== 'editor') return;
                const field = e.target.dataset.field;
                if (!field) return;
                const exerciseCard = e.target.closest('.exercise-card');
                const exerciseIndex = exerciseCard ? parseInt(exerciseCard.dataset.index) : null;
                const workout = this.workouts.find(w => w.id === this.currentWorkoutId);
                if (workout && exerciseIndex !== null) {
                    const value = e.target.value;
                    const exercise = workout.exercises[exerciseIndex];
                    exercise[field] = e.target.type === 'number' ? (value ? parseInt(value) : null) : value;
                    if (field === 'reps' || field === 'time') {
                        const delayGroup = exerciseCard.querySelector('.delay-group');
                        const showDelay = exercise.reps && exercise.time;
                        delayGroup.style.display = showDelay ? 'block' : 'none';
                    }
                }
            });
        },

        goHome() {
            this.currentView = 'home';
            this.currentWorkoutId = null;
            this.render();
        },
        async newWorkout() {
            const w = { id: Date.now(), name: 'New Workout', exercises: [] };
            this.workouts.push(w);
            await this.saveWorkouts();
            this.currentWorkoutId = w.id;
            this.currentView = 'editor';
            this.render();
        },
        editWorkout(id) {
            this.currentWorkoutId = id;
            this.currentView = 'editor';
            this.render();
        },
        async deleteWorkout(id) {
            if (confirm('Permanently delete this workout?')) {
                this.workouts = this.workouts.filter(w => w.id !== id);
                await this.saveWorkouts();
                this.goHome();
            }
        },
        async cloneWorkout(id) {
            const o = this.workouts.find(w => w.id === id);
            if (o) {
                const c = JSON.parse(JSON.stringify(o));
                c.id = Date.now();
                c.name = `${o.name} (Copy)`;
                this.workouts.push(c);
                await this.saveWorkouts();
                this.editWorkout(c.id);
            }
        },
        addExercise() {
            const w = this.workouts.find(w => w.id === this.currentWorkoutId);
            if (w) { w.exercises.push({ name: 'New Exercise', reps: null, time: null, delay: null }); this.render(); }
        },
        deleteExercise(i) {
            const w = this.workouts.find(w => w.id === this.currentWorkoutId);
            if (w) { w.exercises.splice(i, 1); this.render(); }
        },
        moveExercise(i, dir) {
            const w = this.workouts.find(w => w.id === this.currentWorkoutId);
            if (!w) return;
            const newI = i + dir;
            if (newI < 0 || newI >= w.exercises.length) return;
            const [item] = w.exercises.splice(i, 1);
            w.exercises.splice(newI, 0, item);
            this.render();
        },
        async saveWorkoutFromEditor() {
            const workout = this.workouts.find(w => w.id === this.currentWorkoutId);
            if (workout) {
                workout.name = document.getElementById('workout-name').value;
            }
            await this.saveWorkouts();
            this.goHome();
        },
        
        startRunner(id) {
            this.currentWorkoutId = id; this.currentView = 'runner'; this.currentExerciseIndex = 0;
            this.acquireWakeLock();
            if (!this.runnerViewEl) {
                this.runnerViewEl = document.createElement('div');
                this.runnerViewEl.className = 'runner-view';
                this.runnerViewEl.innerHTML = `
                    <button class="runner-close-button" data-action="stop-runner">End Workout</button>
                    <div class="runner-content">
                        <h2 class="runner-exercise-name"></h2><p class="runner-reps" id="runner-reps-display"></p><div class="runner-timer" id="runner-timer-display"></div>
                        <p class="runner-description"></p><button class="button" id="runner-action-button"></button>
                        <div class="timer-controls" id="timer-controls" style="display: none;">
                            <button class="button secondary" id="pause-resume-button"></button><button class="button danger" data-action="reset-timer">Reset</button>
                        </div>
                    </div>
                    <div class="runner-progress"></div>
                    <div class="runner-nav"><div class="nav-button" data-action="prev-exercise">&#8249;</div><div class="nav-button" data-action="next-exercise">&#8250;</div></div>`;
                document.body.appendChild(this.runnerViewEl);
            }
            this.updateRunnerView();
        },
        stopRunner() {
            clearInterval(this.runnerInterval);
            this.releaseWakeLock();
            this.goHome();
        },
        initiateExercise() {
            clearInterval(this.runnerInterval);
            this.timerState = 'idle';
            this.updateRunnerView();
        },
        runGetReadyCountdown() {
            const exercise = this.workouts.find(w => w.id === this.currentWorkoutId).exercises[this.currentExerciseIndex];
            this.runnerViewEl.querySelector('.runner-exercise-name').textContent = `Get Ready: ${exercise.name}`;
            this.runnerViewEl.querySelector('.runner-description').textContent = exercise.description || '';
            this.runnerViewEl.querySelector('#runner-action-button').style.display = 'none';
            this.runnerViewEl.querySelector('#timer-controls').style.display = 'none';
            const timerDisplay = this.runnerViewEl.querySelector('#runner-timer-display');
            let countdown = 3; timerDisplay.textContent = countdown; this.playSound('tick');
            this.runnerInterval = setInterval(() => {
                countdown--;
                if (countdown > 0) {
                    timerDisplay.textContent = countdown; this.playSound('tick');
                } else {
                    clearInterval(this.runnerInterval); this.startCurrentExerciseTimer(true);
                }
            }, 1000);
        },
        updateRunnerView() {
            const workout = this.workouts.find(w => w.id === this.currentWorkoutId);
            if (!workout) { this.stopRunner(); return; }
            const exercise = workout.exercises[this.currentExerciseIndex];
            const isLastExercise = this.currentExerciseIndex === workout.exercises.length - 1;
            
            // Update progress pips
            this.updateProgressPips(workout.exercises.length, this.currentExerciseIndex);
            
            this.runnerViewEl.querySelector('.runner-exercise-name').textContent = exercise.name;
            this.runnerViewEl.querySelector('.runner-description').textContent = exercise.description || '';
            const actionButton = this.runnerViewEl.querySelector('#runner-action-button');
            const repsDisplay = this.runnerViewEl.querySelector('#runner-reps-display');
            const timerDisplay = this.runnerViewEl.querySelector('#runner-timer-display');
            timerDisplay.textContent = '';
            repsDisplay.textContent = '';
            this.runnerViewEl.querySelector('#timer-controls').style.display = 'none';
            actionButton.style.display = 'block';
            if (exercise.reps && !exercise.time) {
                repsDisplay.textContent = `${exercise.reps} Reps`;
                actionButton.textContent = 'Complete';
                actionButton.dataset.action = isLastExercise ? 'finish-workout' : 'next-exercise';
            } else if (exercise.time) {
                repsDisplay.textContent = exercise.reps ? `Set: ${exercise.reps} x ${exercise.time}s` : `Set: ${exercise.time}s`;
                actionButton.textContent = 'Start Exercise';
                actionButton.dataset.action = 'get-ready';
            } else {
                repsDisplay.textContent = '';
                actionButton.textContent = 'Complete';
                actionButton.dataset.action = isLastExercise ? 'finish-workout' : 'next-exercise';
            }
            const prevButton = this.runnerViewEl.querySelector('[data-action="prev-exercise"]');
            const nextButton = this.runnerViewEl.querySelector('[data-action="next-exercise"]');
            prevButton.disabled = this.currentExerciseIndex === 0;
            nextButton.disabled = isLastExercise;
        },
        
        updateProgressPips(totalExercises, currentExercise) {
            const progressContainer = this.runnerViewEl.querySelector('.runner-progress');
            progressContainer.innerHTML = '';
            
            for (let i = 0; i < totalExercises; i++) {
                const pip = document.createElement('div');
                pip.className = `runner-pip ${i === currentExercise ? 'active' : ''}`;
                progressContainer.appendChild(pip);
            }
        },
        startCurrentExerciseTimer(isFirstRep = false) {
            this.timerState = 'running';
            const exercise = this.workouts.find(w => w.id === this.currentWorkoutId).exercises[this.currentExerciseIndex];
            this.runnerViewEl.querySelector('.runner-exercise-name').textContent = exercise.name;
            if (isFirstRep) this.playSound('start');
            this.runnerViewEl.querySelector('#runner-action-button').style.display = 'none';
            this.runnerViewEl.querySelector('#timer-controls').style.display = 'flex';
            const pauseBtn = this.runnerViewEl.querySelector('#pause-resume-button');
            pauseBtn.textContent = 'Pause'; pauseBtn.dataset.action = 'pause-timer';
            if (exercise.reps) {
                this.runRepTimer(exercise, 1);
            } else {
                this.runSingleTimer(exercise.time);
            }
        },
        changeExercise(direction) {
            const workout = this.workouts.find(w => w.id === this.currentWorkoutId);
            if (!workout) { this.stopRunner(); return; }
            const newIndex = this.currentExerciseIndex + direction;
            if (newIndex >= 0 && newIndex < workout.exercises.length) {
                this.currentExerciseIndex = newIndex;
                this.initiateExercise();
            }
        },
        completeExercise() {
            this.playSound('exercise-complete');
            this.timerState = 'idle';
            clearInterval(this.runnerInterval);
            const workout = this.workouts.find(w => w.id === this.currentWorkoutId);
            const isLastExercise = this.currentExerciseIndex === workout.exercises.length - 1;
            if (isLastExercise) {
                this.renderCompletionScreen();
            } else {
                this.runnerViewEl.querySelector('#timer-controls').style.display = 'none';
                const actionButton = this.runnerViewEl.querySelector('#runner-action-button');
                actionButton.style.display = 'block';
                actionButton.textContent = 'Next Exercise';
                actionButton.dataset.action = 'next-exercise';
            }
        },
        renderCompletionScreen() {
            this.playSound('workout-complete');
            const contentEl = this.runnerViewEl.querySelector('.runner-content');
            this.runnerViewEl.querySelector('.runner-nav').style.display = 'none';
            contentEl.innerHTML = `
                <h2 class="runner-exercise-name">Workout Complete!</h2>
                <p class="runner-description">Great job!</p>
                <button class="button" data-action="stop-runner" style="margin-top: 3rem;">Back to Home</button>
            `;
        },
        runSingleTimer(duration) {
            let timeLeft = duration;
            const timerDisplay = this.runnerViewEl.querySelector('#runner-timer-display');
            timerDisplay.textContent = timeLeft;
            this.runnerInterval = setInterval(() => {
                timeLeft--;
                timerDisplay.textContent = timeLeft;
                if (timeLeft > 0 && timeLeft <= 5) this.playSound('countdown');
                if (timeLeft <= 0) {
                    this.completeExercise();
                }
            }, 1000);
        },
        runRepTimer(exercise, currentRep, startTime) {
            this.timerState = 'running';
            const { reps, time, delay } = exercise;
            if (currentRep > 1 && !startTime) this.playSound('rep-start');
            const repsDisplay = this.runnerViewEl.querySelector('#runner-reps-display');
            repsDisplay.textContent = `Rep ${currentRep} / ${reps}`;
            const timerDisplay = this.runnerViewEl.querySelector('#runner-timer-display');
            let timeLeft = startTime || time;
            timerDisplay.textContent = timeLeft;
            this.runnerInterval = setInterval(() => {
                timeLeft--;
                timerDisplay.textContent = timeLeft;
                if (timeLeft > 0 && timeLeft <= 5) this.playSound('countdown');
                if (timeLeft <= 0) {
                    clearInterval(this.runnerInterval);
                    if (currentRep < reps) {
                        this.playSound('rep-complete');
                        setTimeout(() => this.runDelayTimer(exercise, currentRep), 250);
                    } else {
                        this.completeExercise();
                    }
                }
            }, 1000);
        },
        runDelayTimer(exercise, currentRep) {
            this.runnerViewEl.querySelector('#runner-reps-display').textContent = `Rest`;
            const timerDisplay = this.runnerViewEl.querySelector('#runner-timer-display');
            let delayLeft = exercise.delay;
            timerDisplay.textContent = delayLeft;
            this.runnerInterval = setInterval(() => {
                delayLeft--;
                timerDisplay.textContent = delayLeft;
                if (delayLeft > 0) this.playSound('tick');
                if (delayLeft <= 0) {
                    clearInterval(this.runnerInterval);
                    this.runRepTimer(exercise, currentRep + 1);
                }
            }, 1000);
        },
        pauseTimer() {
            if (this.timerState !== 'running') return;
            clearInterval(this.runnerInterval);
            this.timerState = 'paused';
            this.timeRemainingOnPause = parseInt(this.runnerViewEl.querySelector('#runner-timer-display').textContent);
            const repsDisplay = this.runnerViewEl.querySelector('#runner-reps-display').textContent;
            if (repsDisplay.includes('Rep')) {
                this.currentRepOnPause = parseInt(repsDisplay.split(' ')[1]);
            }
            const pauseResumeBtn = this.runnerViewEl.querySelector('#pause-resume-button');
            pauseResumeBtn.textContent = 'Resume';
            pauseResumeBtn.dataset.action = 'resume-timer';
        },
        resumeTimer() {
            if (this.timerState !== 'paused') return;
            this.timerState = 'running';
            const exercise = this.workouts.find(w => w.id === this.currentWorkoutId).exercises[this.currentExerciseIndex];
            const pauseResumeBtn = this.runnerViewEl.querySelector('#pause-resume-button');
            pauseResumeBtn.textContent = 'Pause';
            pauseResumeBtn.dataset.action = 'pause-timer';
            if (exercise.reps) {
                this.runRepTimer(exercise, this.currentRepOnPause, this.timeRemainingOnPause);
            } else {
                this.runSingleTimer(this.timeRemainingOnPause);
            }
        },
        resetTimer() {
            clearInterval(this.runnerInterval);
            this.timerState = 'idle';
            this.updateRunnerView();
        }
    };

    await app.init();
});
