//! History/TTL parsing for mi6.
//!
//! This module handles parsing of history period strings like "7d", "24h", "30m".

use std::time::Duration;

use crate::model::error::TtlParseError;

/// Default history period: 1000 days
pub const DEFAULT_HISTORY: Duration = Duration::from_secs(1000 * 24 * 60 * 60);

/// Default history string for serde
pub(crate) fn default_history_string() -> String {
    "1000d".to_string()
}

/// Parse a history/TTL string like "7d", "30d", "1h" into a Duration.
///
/// Supports suffixes:
/// - 'd' for days (e.g., "7d" = 7 days)
/// - 'h' for hours (e.g., "24h" = 24 hours)
/// - 'm' for minutes (e.g., "30m" = 30 minutes)
/// - 's' for seconds (e.g., "3600s" = 1 hour)
/// - Raw seconds if no suffix (e.g., "86400" = 1 day)
pub fn parse_history(s: &str) -> Result<Duration, TtlParseError> {
    let s = s.trim();
    if let Some(stripped) = s.strip_suffix('d') {
        let days: u64 = stripped
            .parse()
            .map_err(|_| TtlParseError::InvalidNumber(s.to_string()))?;
        Ok(Duration::from_secs(days * 24 * 60 * 60))
    } else if let Some(stripped) = s.strip_suffix('h') {
        let hours: u64 = stripped
            .parse()
            .map_err(|_| TtlParseError::InvalidNumber(s.to_string()))?;
        Ok(Duration::from_secs(hours * 60 * 60))
    } else if let Some(stripped) = s.strip_suffix('m') {
        let minutes: u64 = stripped
            .parse()
            .map_err(|_| TtlParseError::InvalidNumber(s.to_string()))?;
        Ok(Duration::from_secs(minutes * 60))
    } else if let Some(stripped) = s.strip_suffix('s') {
        let secs: u64 = stripped
            .parse()
            .map_err(|_| TtlParseError::InvalidNumber(s.to_string()))?;
        Ok(Duration::from_secs(secs))
    } else {
        // Assume seconds (raw number)
        let secs: u64 = s
            .parse()
            .map_err(|_| TtlParseError::InvalidFormat(s.to_string()))?;
        Ok(Duration::from_secs(secs))
    }
}

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

    #[test]
    fn test_parse_history() {
        // Days
        assert_eq!(
            parse_history("7d"),
            Ok(Duration::from_secs(7 * 24 * 60 * 60))
        );
        assert_eq!(
            parse_history("30d"),
            Ok(Duration::from_secs(30 * 24 * 60 * 60))
        );

        // Hours
        assert_eq!(parse_history("1h"), Ok(Duration::from_secs(60 * 60)));
        assert_eq!(parse_history("24h"), Ok(Duration::from_secs(24 * 60 * 60)));

        // Minutes
        assert_eq!(parse_history("30m"), Ok(Duration::from_secs(30 * 60)));
        assert_eq!(parse_history("60m"), Ok(Duration::from_secs(60 * 60)));

        // Seconds (raw number)
        assert_eq!(parse_history("1000"), Ok(Duration::from_secs(1000)));

        // Explicit seconds suffix
        assert_eq!(parse_history("3600s"), Ok(Duration::from_secs(3600)));

        // Invalid
        assert_eq!(
            parse_history("abc"),
            Err(TtlParseError::InvalidFormat("abc".to_string()))
        );
        assert_eq!(
            parse_history("d"),
            Err(TtlParseError::InvalidNumber("d".to_string()))
        );
    }

    #[test]
    fn test_default_history_constant() {
        // DEFAULT_HISTORY should be 1000 days in seconds
        assert_eq!(DEFAULT_HISTORY, Duration::from_secs(1000 * 24 * 60 * 60));
    }
}
