use crate::session::result::DrillResult;

pub fn compute_score(result: &DrillResult, complexity: f64) -> f64 {
    let speed = result.cpm;
    let errors = result.incorrect as f64;
    let length = result.total_chars as f64;
    (speed * complexity) / (errors + 1.0) * (length / 50.0)
}

#[allow(dead_code)]
pub fn compute_complexity(unlocked_count: usize, total_keys: usize) -> f64 {
    (unlocked_count as f64 / total_keys as f64).max(0.1)
}

pub fn level_from_score(total_score: f64) -> u32 {
    let level = (total_score / 100.0).sqrt() as u32;
    level.max(1)
}

#[allow(dead_code)]
pub fn score_to_next_level(total_score: f64) -> f64 {
    let current_level = level_from_score(total_score);
    let next_level_score = ((current_level + 1) as f64).powi(2) * 100.0;
    next_level_score - total_score
}

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

    #[test]
    fn test_level_starts_at_one() {
        assert_eq!(level_from_score(0.0), 1);
    }

    #[test]
    fn test_level_increases_with_score() {
        assert!(level_from_score(1000.0) > level_from_score(100.0));
    }

    #[test]
    fn test_complexity_scales_with_keys() {
        assert!(compute_complexity(96, 96) > compute_complexity(6, 96));
        assert!((compute_complexity(96, 96) - 1.0).abs() < 0.001);
    }
}
