//! Audio and video playback settings commands.
//!
//! TRACES: UR-022, UR-027, UR-031, UR-032, UR-033 | DR-025, DR-030, DR-034, DR-035, DR-036, IR-020

use tauri::State;

use super::{PlayerStateWrapper, VideoSettingsWrapper};
use crate::player::AutoplaySettings;
use crate::settings::{AudioSettings, EqPreset, VideoSettings};

#[tauri::command]
#[specta::specta]
pub async fn player_set_audio_settings(
    player: State<'_, PlayerStateWrapper>,
    settings: AudioSettings,
) -> Result<AudioSettings, String> {
    // Validate/normalise domain values before applying: clamp crossfade to its
    // range and normalise the equalizer band vector (length + gain clamps).
    let validated = settings
        .with_crossfade_clamped()
        .with_equalizer_normalised();
    let mut controller = player.0.lock().await;
    controller
        .set_audio_settings(&validated)
        .map_err(|e| e.to_string())?;
    Ok(controller.audio_settings())
}

/// The built-in equalizer presets and their per-band gain curves (dB), for the
/// settings UI. The curve numbers are domain data defined by the band layout,
/// so the frontend reads them here rather than encoding them.
///
/// TRACES: UR-027 | DR-030
#[tauri::command]
#[specta::specta]
pub async fn player_get_eq_presets() -> Result<Vec<(EqPreset, Vec<f32>)>, String> {
    Ok(EqPreset::ALL
        .iter()
        .map(|p| (*p, p.gains().to_vec()))
        .collect())
}

#[tauri::command]
#[specta::specta]
pub async fn player_get_audio_settings(
    player: State<'_, PlayerStateWrapper>,
) -> Result<AudioSettings, String> {
    let controller = player.0.lock().await;
    Ok(controller.audio_settings())
}

#[tauri::command]
#[specta::specta]
pub async fn player_set_video_settings(
    video_settings: State<'_, VideoSettingsWrapper>,
    player: State<'_, PlayerStateWrapper>,
    settings: VideoSettings,
) -> Result<VideoSettings, String> {
    let validated = settings.with_countdown_clamped();
    {
        let mut current = video_settings.0.lock().map_err(|e| e.to_string())?;
        *current = validated.clone();
    } // Drop MutexGuard before await

    // Sync to PlayerController's autoplay settings so on_playback_ended() uses current values
    let controller = player.0.lock().await;
    controller.set_autoplay_settings(AutoplaySettings {
        enabled: validated.auto_play_next_episode,
        countdown_seconds: validated.auto_play_countdown_seconds,
        max_episodes: validated.auto_play_max_episodes,
    });

    Ok(validated)
}

#[tauri::command]
#[specta::specta]
pub async fn player_get_video_settings(
    video_settings: State<'_, VideoSettingsWrapper>,
) -> Result<VideoSettings, String> {
    let current = video_settings.0.lock().map_err(|e| e.to_string())?;
    Ok(current.clone())
}
