/**
 * Work Break Timer Logic
 */

// Constants
const DEFAULT_TIME_MINUTES = 22;
const MAX_TIME_MINUTES = 180;
const SECONDS_PER_MINUTE = 60;

// State
let timeLeft = DEFAULT_TIME_MINUTES * SECONDS_PER_MINUTE; // in seconds
let isRunning = false;
let intervalId: number | null = null;
let audioContext: AudioContext | null = null;

// DOM Elements
const timerDisplay = document.getElementById('timerDisplay') as HTMLElement;
const startBtn = document.getElementById('startBtn') as HTMLButtonElement;
const resetBtn = document.getElementById('resetBtn') as HTMLButtonElement;
const adjustButtons = document.querySelectorAll('.adjust-btn');

/**
 * Formats seconds into MM:SS string
 */
function formatTime(seconds: number): string {
    const m = Math.floor(seconds / 60);
    const s = seconds % 60;
    return `${m.toString().padStart(2, '0')}:${s.toString().padStart(2, '0')}`;
}

/**
 * Updates the timer display
 */
function updateDisplay(): void {
    timerDisplay.textContent = formatTime(timeLeft);

    // Update document title
    document.title = `${formatTime(timeLeft)} - Work Timer`;
}

/**
 * Plays a simple beep sound using AudioContext
 */
function playAlarm(): void {
    if (!audioContext) {
        audioContext = new (window.AudioContext || (window as any).webkitAudioContext)();
    }

    // Create oscillator
    const oscillator = audioContext.createOscillator();
    const gainNode = audioContext.createGain();

    oscillator.type = 'sine';
    oscillator.frequency.setValueAtTime(880, audioContext.currentTime); // A5
    oscillator.frequency.exponentialRampToValueAtTime(440, audioContext.currentTime + 0.5); // Drop to A4

    gainNode.gain.setValueAtTime(0.5, audioContext.currentTime);
    gainNode.gain.exponentialRampToValueAtTime(0.01, audioContext.currentTime + 0.5);

    oscillator.connect(gainNode);
    gainNode.connect(audioContext.destination);

    oscillator.start();
    oscillator.stop(audioContext.currentTime + 0.5);
}

/**
 * Handles the timer tick
 */
function onTick(): void {
    if (timeLeft > 0) {
        timeLeft--;
        updateDisplay();
    } else {
        // Time is up
        pauseTimer();
        timerDisplay.classList.add('time-up');
        playAlarm();
        // Play alarm 3 times
        setTimeout(playAlarm, 1000);
        setTimeout(playAlarm, 2000);
    }
}

/**
 * Starts or resumes the timer
 */
function startTimer(): void {
    if (timeLeft === 0) {
        // If time is 0, reset to default before starting? 
        // Or just do nothing? Requirement says: "Start from currently set time".
        // If currently set is 0, we can't really start.
        // Let's assume if 0, we reset to default for convenience, or just return.
        // Let's just return to be safe, or maybe the user wants to add time first.
        if (timeLeft === 0) return;
    }

    if (!isRunning) {
        isRunning = true;
        startBtn.textContent = 'Pause';
        timerDisplay.classList.remove('time-up');

        // Use window.setInterval to avoid TypeScript confusion with NodeJS.Timeout
        intervalId = window.setInterval(onTick, 1000);
    } else {
        // Pause
        pauseTimer();
    }
}

/**
 * Pauses the timer
 */
function pauseTimer(): void {
    isRunning = false;
    startBtn.textContent = 'Resume';
    if (intervalId !== null) {
        clearInterval(intervalId);
        intervalId = null;
    }
}

/**
 * Resets the timer
 */
function resetTimer(): void {
    pauseTimer();
    timeLeft = DEFAULT_TIME_MINUTES * SECONDS_PER_MINUTE;
    startBtn.textContent = 'Start';
    timerDisplay.classList.remove('time-up');
    updateDisplay();
    document.title = 'Work Break Timer';
}

/**
 * Adjusts the time by adding minutes
 */
function adjustTime(minutes: number): void {
    const newTime = timeLeft + (minutes * SECONDS_PER_MINUTE);
    const maxSeconds = MAX_TIME_MINUTES * SECONDS_PER_MINUTE;

    if (newTime <= maxSeconds) {
        timeLeft = newTime;
        updateDisplay();

        // If timer finished and we add time, remove the alarm style
        if (timeLeft > 0) {
            timerDisplay.classList.remove('time-up');
        }
    } else {
        // Cap at max
        timeLeft = maxSeconds;
        updateDisplay();
    }
}

// Event Listeners
startBtn.addEventListener('click', startTimer);
resetBtn.addEventListener('click', resetTimer);

adjustButtons.forEach(btn => {
    btn.addEventListener('click', () => {
        const minutes = parseInt(btn.getAttribute('data-minutes') || '0', 10);
        adjustTime(minutes);
    });
});

// Initialize
updateDisplay();
