//! Time utilities (enabled with "time" feature)

#[cfg(feature = "time")]
use chrono::{DateTime, Utc, TimeZone};

/// Time formatting utilities
#[cfg(feature = "time")]
pub mod format {
    use super::*;

    /// Format timestamp for display in different languages
    pub fn display_date(timestamp: &str, language: &str) -> Result<String, chrono::ParseError> {
        let dt = DateTime::parse_from_rfc3339(timestamp)?
            .with_timezone(&Utc);

        match language {
            "es" => Ok(dt.format("%d de %B de %Y").to_string()),
            _ => Ok(dt.format("%B %d, %Y").to_string()),
        }
    }

    /// Format timestamp with time for display
    pub fn display_datetime(timestamp: &str, language: &str) -> Result<String, chrono::ParseError> {
        let dt = DateTime::parse_from_rfc3339(timestamp)?
            .with_timezone(&Utc);

        match language {
            "es" => Ok(dt.format("%d de %B de %Y a las %H:%M UTC").to_string()),
            _ => Ok(dt.format("%B %d, %Y at %H:%M UTC").to_string()),
        }
    }

    /// Format relative time (e.g., "2 hours ago")
    pub fn relative_time(timestamp: &str, language: &str) -> Result<String, chrono::ParseError> {
        let dt = DateTime::parse_from_rfc3339(timestamp)?
            .with_timezone(&Utc);
        let now = Utc::now();
        let diff = now.signed_duration_since(dt);

        let (value, unit) = if diff.num_seconds() < 60 {
            (diff.num_seconds(), match language {
                "es" => if diff.num_seconds() == 1 { "segundo" } else { "segundos" },
                _ => if diff.num_seconds() == 1 { "second" } else { "seconds" },
            })
        } else if diff.num_minutes() < 60 {
            (diff.num_minutes(), match language {
                "es" => if diff.num_minutes() == 1 { "minuto" } else { "minutos" },
                _ => if diff.num_minutes() == 1 { "minute" } else { "minutes" },
            })
        } else if diff.num_hours() < 24 {
            (diff.num_hours(), match language {
                "es" => if diff.num_hours() == 1 { "hora" } else { "horas" },
                _ => if diff.num_hours() == 1 { "hour" } else { "hours" },
            })
        } else {
            (diff.num_days(), match language {
                "es" => if diff.num_days() == 1 { "día" } else { "días" },
                _ => if diff.num_days() == 1 { "day" } else { "days" },
            })
        };

        let ago = match language {
            "es" => "hace",
            _ => "ago",
        };

        Ok(format!("{} {} {}", value, unit, ago))
    }
}

/// Time zone utilities
#[cfg(feature = "time")]
pub mod timezone {
    use super::*;

    /// Convert UTC timestamp to local timezone display
    pub fn to_local_display(timestamp: &str) -> Result<String, chrono::ParseError> {
        let dt = DateTime::parse_from_rfc3339(timestamp)?;
        // In WASM, we can't access system timezone easily, so return UTC
        Ok(dt.format("%Y-%m-%d %H:%M UTC").to_string())
    }

    /// Get common timezone offsets
    pub fn common_timezones() -> Vec<(&'static str, i32)> {
        vec![
            ("UTC", 0),
            ("EST", -5),
            ("PST", -8),
            ("CET", 1),
            ("JST", 9),
        ]
    }
}

/// Duration utilities
#[cfg(feature = "time")]
pub mod duration {
    use chrono::Duration;

    /// Parse duration from string (e.g., "1h30m", "45s")
    pub fn parse_duration(input: &str) -> Result<Duration, String> {
        let mut total_seconds = 0i64;
        let mut current_number = String::new();

        for ch in input.chars() {
            if ch.is_ascii_digit() {
                current_number.push(ch);
            } else if ch.is_alphabetic() {
                if current_number.is_empty() {
                    return Err("No number before unit".to_string());
                }

                let number: i64 = current_number.parse()
                    .map_err(|_| "Invalid number")?;

                let seconds = match ch {
                    's' => number,
                    'm' => number * 60,
                    'h' => number * 3600,
                    'd' => number * 86400,
                    _ => return Err(format!("Unknown unit: {}", ch)),
                };

                total_seconds += seconds;
                current_number.clear();
            } else if ch.is_whitespace() {
                continue;
            } else {
                return Err(format!("Invalid character: {}", ch));
            }
        }

        if !current_number.is_empty() {
            // Assume seconds if no unit specified
            let number: i64 = current_number.parse()
                .map_err(|_| "Invalid number")?;
            total_seconds += number;
        }

        Ok(Duration::seconds(total_seconds))
    }

    /// Format duration for display
    pub fn format_duration(duration: Duration, language: &str) -> String {
        let total_seconds = duration.num_seconds();

        if total_seconds < 60 {
            match language {
                "es" => format!("{} segundos", total_seconds),
                _ => format!("{} seconds", total_seconds),
            }
        } else if total_seconds < 3600 {
            let minutes = total_seconds / 60;
            match language {
                "es" => format!("{} minutos", minutes),
                _ => format!("{} minutes", minutes),
            }
        } else if total_seconds < 86400 {
            let hours = total_seconds / 3600;
            let remaining_minutes = (total_seconds % 3600) / 60;
            if remaining_minutes == 0 {
                match language {
                    "es" => format!("{} horas", hours),
                    _ => format!("{} hours", hours),
                }
            } else {
                match language {
                    "es" => format!("{} horas {} minutos", hours, remaining_minutes),
                    _ => format!("{} hours {} minutes", hours, remaining_minutes),
                }
            }
        } else {
            let days = total_seconds / 86400;
            match language {
                "es" => format!("{} días", days),
                _ => format!("{} days", days),
            }
        }
    }
}

// No-op implementations for when time feature is not enabled
#[cfg(not(feature = "time"))]
pub mod format {
    pub fn display_date(_timestamp: &str, _language: &str) -> Result<String, &'static str> {
        Err("Time feature not enabled")
    }

    pub fn display_datetime(_timestamp: &str, _language: &str) -> Result<String, &'static str> {
        Err("Time feature not enabled")
    }

    pub fn relative_time(_timestamp: &str, _language: &str) -> Result<String, &'static str> {
        Err("Time feature not enabled")
    }
}

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

    #[cfg(feature = "time")]
    #[test]
    fn test_duration_parsing() {
        use duration::parse_duration;

        assert_eq!(parse_duration("30s").unwrap().num_seconds(), 30);
        assert_eq!(parse_duration("5m").unwrap().num_seconds(), 300);
        assert_eq!(parse_duration("2h").unwrap().num_seconds(), 7200);
        assert_eq!(parse_duration("1d").unwrap().num_seconds(), 86400);
        assert_eq!(parse_duration("1h30m").unwrap().num_seconds(), 5400);
        assert_eq!(parse_duration("120").unwrap().num_seconds(), 120); // No unit = seconds

        assert!(parse_duration("invalid").is_err());
        assert!(parse_duration("5x").is_err()); // Invalid unit
    }

    #[cfg(feature = "time")]
    #[test]
    fn test_duration_formatting() {
        use duration::{parse_duration, format_duration};

        let dur = parse_duration("30s").unwrap();
        assert_eq!(format_duration(dur, "en"), "30 seconds");
        assert_eq!(format_duration(dur, "es"), "30 segundos");

        let dur = parse_duration("5m").unwrap();
        assert_eq!(format_duration(dur, "en"), "5 minutes");
        assert_eq!(format_duration(dur, "es"), "5 minutos");

        let dur = parse_duration("2h30m").unwrap();
        assert_eq!(format_duration(dur, "en"), "2 hours 30 minutes");
        assert_eq!(format_duration(dur, "es"), "2 horas 30 minutos");
    }

    #[cfg(not(feature = "time"))]
    #[test]
    fn test_time_feature_disabled() {
        let result = format::display_date("2023-01-01T00:00:00Z", "en");
        assert!(result.is_err());
    }
}
