use crate::error::{CommonResult as Result, CommonError as Error};

/// Format duration in human-readable format
pub fn format_duration(seconds: u32) -> 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)
    }
}

/// Format file size in human-readable format
pub fn format_file_size(bytes: u64) -> String {
    const UNITS: &[&str] = &["B", "KB", "MB", "GB", "TB"];
    const THRESHOLD: u64 = 1024;
    
    if bytes == 0 {
        return "0 B".to_string();
    }
    
    let mut size = bytes as f64;
    let mut unit_index = 0;
    
    while size >= THRESHOLD as f64 && unit_index < UNITS.len() - 1 {
        size /= THRESHOLD as f64;
        unit_index += 1;
    }
    
    if unit_index == 0 {
        format!("{} {}", bytes, UNITS[unit_index])
    } else {
        format!("{:.1} {}", size, UNITS[unit_index])
    }
}

/// Format number with thousands separator
pub fn format_number(n: u64) -> String {
    let s = n.to_string();
    let mut result = String::new();
    let mut count = 0;
    
    for c in s.chars().rev() {
        if count > 0 && count % 3 == 0 {
            result.push(',');
        }
        result.push(c);
        count += 1;
    }
    
    result.chars().rev().collect()
}

/// Truncate string to specified length
pub fn truncate_string(s: &str, max_length: usize) -> String {
    if s.len() <= max_length {
        s.to_string()
    } else {
        format!("{}...", &s[..max_length.saturating_sub(3)])
    }
}

/// Check if string is empty or whitespace only
pub fn is_empty_or_whitespace(s: &str) -> bool {
    s.trim().is_empty()
}

/// Convert string to slug
pub fn to_slug(input: &str) -> String {
    input
        .to_lowercase()
        .chars()
        .map(|c| match c {
            ' ' => '-',
            c if c.is_alphanumeric() => c,
            _ => '-',
        })
        .collect::<String>()
        .split('-')
        .filter(|s| !s.is_empty())
        .collect::<Vec<&str>>()
        .join("-")
}

/// Parse duration string (e.g., "1h30m", "45s")
pub fn parse_duration(duration_str: &str) -> Result<u64> {
    let mut total_seconds = 0u64;
    let mut current_number = String::new();
    
    for c in duration_str.chars() {
        if c.is_numeric() {
            current_number.push(c);
        } else {
            if !current_number.is_empty() {
                let number: u64 = current_number.parse()
                    .map_err(|_| Error::ValidationError(format!("Invalid duration: {}", duration_str)))?;
                
                match c {
                    's' => total_seconds += number,
                    'm' => total_seconds += number * 60,
                    'h' => total_seconds += number * 3600,
                    'd' => total_seconds += number * 86400,
                    _ => return Err(Error::ValidationError(format!("Invalid duration unit: {}", c))),
                }
                
                current_number.clear();
            }
        }
    }
    
    // Handle case where duration ends with a number (assume seconds)
    if !current_number.is_empty() {
        let number: u64 = current_number.parse()
            .map_err(|_| Error::ValidationError(format!("Invalid duration: {}", duration_str)))?;
        total_seconds += number;
    }
    
    Ok(total_seconds)
}

/// Sanitize string input
pub fn sanitize_string(input: &str) -> String {
    input
        .chars()
        .filter(|c| !c.is_control() || *c == '\n' || *c == '\r' || *c == '\t')
        .collect::<String>()
        .trim()
        .to_string()
}
