// Autoplay decision logic
// TRACES: UR-023, UR-026 | DR-047, DR-048, DR-029
use crate::repository::types::MediaItem;
use serde::{Deserialize, Serialize};

/// Autoplay decision result - determines what happens after playback ends
#[derive(specta::Type, Debug, Clone, Serialize)]
#[serde(tag = "action", rename_all = "camelCase")]
pub enum AutoplayDecision {
    /// Stop playback (no next item or timer expired)
    Stop,
    /// Advance to next track in queue (for audio/movies)
    AdvanceToNext,
    /// The stream ended well short of the item's runtime — the connection
    /// dropped, not the media. Re-open the same stream at `position` instead of
    /// running any end-of-item logic (UR-040).
    ResumeStream { position: f64 },
    /// Show next episode popup with countdown
    ShowNextEpisodePopup {
        current_episode: MediaItem,
        next_episode: MediaItem,
        countdown_seconds: u32,
        auto_advance: bool,
    },
}

/// Autoplay settings (controls next episode behavior)
#[derive(specta::Type, Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct AutoplaySettings {
    /// Whether autoplay is enabled for next episodes
    pub enabled: bool,
    /// Countdown duration in seconds before auto-playing next episode
    pub countdown_seconds: u32,
    /// Maximum number of episodes to auto-play consecutively (0 = unlimited)
    #[serde(default)]
    pub max_episodes: u32,
}

impl Default for AutoplaySettings {
    fn default() -> Self {
        Self {
            enabled: true,
            countdown_seconds: 10,
            max_episodes: 0,
        }
    }
}

impl AutoplaySettings {
    /// Validate and clamp countdown seconds to reasonable range (5-30 seconds)
    pub fn with_validated_countdown(mut self) -> Self {
        self.countdown_seconds = self.countdown_seconds.clamp(5, 30);
        self
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_autoplay_settings_defaults() {
        let settings = AutoplaySettings::default();
        assert!(settings.enabled);
        assert_eq!(settings.countdown_seconds, 10);
        assert_eq!(settings.max_episodes, 0);
    }

    #[test]
    fn test_autoplay_settings_backward_compat() {
        // Deserialize old JSON without max_episodes field
        let json = r#"{"enabled":true,"countdownSeconds":15}"#;
        let settings: AutoplaySettings = serde_json::from_str(json).unwrap();
        assert!(settings.enabled);
        assert_eq!(settings.countdown_seconds, 15);
        assert_eq!(settings.max_episodes, 0); // defaults to 0 (unlimited)
    }

    #[test]
    fn test_autoplay_settings_with_max_episodes() {
        let json = r#"{"enabled":true,"countdownSeconds":10,"maxEpisodes":5}"#;
        let settings: AutoplaySettings = serde_json::from_str(json).unwrap();
        assert_eq!(settings.max_episodes, 5);
    }

    #[test]
    fn test_countdown_validation() {
        let settings = AutoplaySettings {
            enabled: true,
            countdown_seconds: 2, // Too short
            max_episodes: 0,
        }
        .with_validated_countdown();
        assert_eq!(settings.countdown_seconds, 5); // Clamped to min

        let settings = AutoplaySettings {
            enabled: true,
            countdown_seconds: 60, // Too long
            max_episodes: 0,
        }
        .with_validated_countdown();
        assert_eq!(settings.countdown_seconds, 30); // Clamped to max

        let settings = AutoplaySettings {
            enabled: true,
            countdown_seconds: 15, // Valid
            max_episodes: 0,
        }
        .with_validated_countdown();
        assert_eq!(settings.countdown_seconds, 15); // Unchanged
    }
}
