//! Utilities module
//! 
//! This module provides utility functions and helpers.

pub mod validation;
pub mod serialization;
pub mod date;
pub mod logging;

pub use validation::*;
pub use serialization::*;
pub use date::*;
pub use logging::*;

// Re-export other utility functions
use uuid::Uuid;

/// Generate a new UUID v4
pub fn generate_uuid() -> Uuid {
    Uuid::new_v4()
}

/// Format a duration in seconds to a human-readable string
pub fn format_duration(seconds: u64) -> String {
    let hours = seconds / 3600;
    let minutes = (seconds % 3600) / 60;
    let secs = seconds % 60;

    if hours > 0 {
        format!("{}:{:02}:{:02}", hours, minutes, secs)
    } else {
        format!("{}:{:02}", minutes, secs)
    }
}

/// Parse a duration string to seconds
/// Supports formats: "MM:SS", "HH:MM:SS"
pub fn parse_duration(duration_str: &str) -> Option<u64> {
    let parts: Vec<&str> = duration_str.split(':').collect();
    
    match parts.len() {
        2 => {
            // MM:SS format
            let minutes: u64 = parts[0].parse().ok()?;
            let seconds: u64 = parts[1].parse().ok()?;
            Some(minutes * 60 + seconds)
        }
        3 => {
            // HH:MM:SS format
            let hours: u64 = parts[0].parse().ok()?;
            let minutes: u64 = parts[1].parse().ok()?;
            let seconds: u64 = parts[2].parse().ok()?;
            Some(hours * 3600 + minutes * 60 + seconds)
        }
        _ => None,
    }
}

/// Format a file size in bytes to a human-readable string
pub fn format_file_size(bytes: u64) -> String {
    const UNITS: &[&str] = &["B", "KB", "MB", "GB", "TB"];
    const THRESHOLD: f64 = 1024.0;

    if bytes == 0 {
        return "0 B".to_string();
    }

    let bytes_f64 = bytes as f64;
    let exp = (bytes_f64.ln() / THRESHOLD.ln()) as u32;
    let exp = exp.min((UNITS.len() - 1) as u32);
    let value = bytes_f64 / THRESHOLD.powi(exp as i32);

    format!("{:.2} {}", value, UNITS[exp as usize])
}

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

    #[test]
    fn test_generate_uuid() {
        let uuid1 = generate_uuid();
        let uuid2 = generate_uuid();
        assert_ne!(uuid1, uuid2);
    }

    #[test]
    fn test_format_duration() {
        assert_eq!(format_duration(0), "0:00");
        assert_eq!(format_duration(65), "1:05");
        assert_eq!(format_duration(3665), "1:01:05");
        assert_eq!(format_duration(3600), "1:00:00");
    }

    #[test]
    fn test_parse_duration() {
        assert_eq!(parse_duration("1:05"), Some(65));
        assert_eq!(parse_duration("1:01:05"), Some(3665));
        assert_eq!(parse_duration("invalid"), None);
        assert_eq!(parse_duration("1:2:3:4"), None);
    }

    #[test]
    fn test_format_file_size() {
        assert_eq!(format_file_size(0), "0 B");
        assert_eq!(format_file_size(1024), "1.00 KB");
        assert_eq!(format_file_size(1048576), "1.00 MB");
        assert_eq!(format_file_size(1073741824), "1.00 GB");
    }
}

