use crossterm::{style::Stylize, terminal::size};
use serde::{Deserialize, Serialize};

use super::units::Module;

#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
pub(crate) struct Tracker {
    pub(crate) unit: Module,
    questions_answered: u64,
    questions_correct: u64,
    probability_known: f64,
    results: Vec<bool>, // Vector to store correct/incorrect results
    milestones: usize,
    milestones_completed: usize,
}

impl Tracker {
    pub(crate) fn new(unit: Module) -> Self {
        Self {
            unit,
            questions_answered: 0,
            questions_correct: 0,
            probability_known: 0.3, // Start with a 30% chance of knowing the answer
            results: Vec::new(),
            milestones: 0,
            milestones_completed: 0,
        }
    }

    pub(crate) fn quiz_result(&mut self, correct: bool) -> f64 {
        self.questions_answered += 1;
        self.results.push(correct);
        if correct {
            self.milestones_completed = (self.milestones_completed + 1).min(self.milestones);
            self.questions_correct += 1;
        }

        // Calculate streak of correct answers
        let mut streak = 0;
        for &result in self.results.iter().rev() {
            if result {
                streak += 1;
            } else {
                break;
            }
        }

        let prior = self.probability_known;
        let slip = if self.questions_answered < 10 {
            0.05 // Lower slip rate for beginners
        } else if self.probability_known > 0.8 {
            0.15 // Higher slip rate for advanced students
        } else {
            0.1 // Default slip rate
        };
        let guess = if self.questions_answered < 10 {
            0.2 // Lower guess rate for beginners
        } else if self.probability_known > 0.8 {
            0.3 // Higher guess rate for advanced students
        } else {
            0.25 // Default guess rate (average of 4 options)
        };
        let likelihood = if correct {
            1.0 - slip
        } else {
            guess
        };

        // Adjust posterior based on streak
        let streak_multiplier = 1.0 + (streak as f64 * 0.1); // Increase probability for streaks
        let posterior = if prior == 0.0 {
            likelihood * streak_multiplier // Start with likelihood if prior is zero
        } else {
            ((likelihood * prior) / ((likelihood * prior) + ((1.0 - likelihood) * (1.0 - prior)))) * streak_multiplier
        };

        self.probability_known = posterior.min(1.0).max(0.0);

        self.probability_known
    }

    pub(crate) fn get_probability(&self) -> f64 {
        // self.probability_known
        if self.milestones == 0 {
            return 0.0;
        }
        if self.milestones_completed == 0 {
            return 0.0;
        }
        self.milestones_completed as f64 / self.milestones as f64
    }

    // pub fn get_milestones(&self) -> usize {
    //     self.milestones
    // }
    // pub fn get_milestones_completed(&self) -> usize {
    //     self.milestones_completed
    // }

    pub(crate) fn print_progress(&self) {
        let (cols, _) = size().unwrap();
        // let percent = self.probability_known * 100.0; // Assuming `probability_known` is a method in `LessonTracker`
        let percent = if self.milestones_completed > 0 {
            (self.milestones_completed as f64) / (self.milestones as f64) * 100.0 // Assuming `probability_known` is a method in `LessonTracker`
        } else {0.0};
        let percent_name = format!("{:>4.0}%", percent).dark_blue();
        let unit_name = format!("{} {} ", percent_name, self.unit);
        let dots = ".".repeat((cols as usize).saturating_sub(unit_name.len() + 11));
        match percent {
            percent if percent > 0.0 => {
                let progress = percent as usize;
                let filled_percent = progress / 5; // Each '=' represents 5%
                let bars = format!(
                    "|{}{}|",
                    "█".repeat(filled_percent),
                    " ".repeat(20_usize.saturating_sub(filled_percent)),
                );
                println!(
                    "{} {} {}",
                    unit_name,
                    dots,
                    bars,
                );
            }
            _ => {
                println!(
                    "{} {} |{}|",
                    unit_name,
                    dots,
                    " ".repeat(20),
                );
            }
        }
    }
    pub fn set_milestones(&mut self, milestones: usize) {
        self.milestones = milestones;
    }
    pub fn set_completed_milestones(&mut self, completed_milestones: usize) {
        self.milestones_completed = completed_milestones;
    }
}