use std::collections::HashMap;

use crossterm::style::Stylize;
use crossterm::terminal::size;
use serde::{Deserialize, Serialize};
use crate::course::{units, tracker};
use crate::{files, printers};
use crate::printers::{clear_console, wait_for_input};
use crate::utilities::questions;

#[serde_with::serde_as]
#[derive(Serialize, Deserialize, Debug)]
pub struct Learner {
    pub name: String,
    pub filename: String,
    #[serde_as(as = "HashMap<serde_with::json::JsonString, _>")]
    pub progress: HashMap<units::Module, tracker::Tracker>,
}

impl Learner {
    pub fn new() -> Self {
        let previous_saves = files::get_previous_saves();

        let user = questions::ask_mcq(
            "Please select or create a user profile.",
            &previous_saves.iter().map(String::as_str).collect::<Vec<&str>>(),
        ).unwrap();

        let learner;

        if user == "Create New" {            
            let name = questions::ask_name();
            let sanitized_name = files::sanitize_name(name.as_str());
            let filename = format!("saves/{}.json", sanitized_name);
            let modules = units::Module::iter();
            let mut progress = HashMap::new();
            for module in modules {
                progress.insert(module.clone(), tracker::Tracker::new(module));
            }
            learner = Self {
                name: name.clone(),
                filename: filename.clone(),
                progress: progress.clone(),
            };
            files::save_to_file(&filename, &learner).expect("Failed to create new profile file");
            printers::print_boxed(&format!("Profile created for {}. Your progress will be saved in {}.", name, filename), printers::StatementType::Default);
            printers::print_boxed("You won't have any progress yet, but the next screen shows what your progress report will look like. Fill all the progress bars to win.", printers::StatementType::Default);
        } else {
            let sanitized_name = files::sanitize_name(&user);
            let filename = format!("saves/{}.json", sanitized_name);
            learner = files::load_from_file(&filename).expect("Failed to load profile file");
            printers::print_boxed(&format!("Profile loaded for {}.", user), printers::StatementType::Default);
        }
        learner.display_progress();
        return learner
    }

    pub fn display_progress(&self) {

        clear_console();
        
        let (cols, _) = size().unwrap();
        let dashes = "-".repeat((cols as usize));
        let dots = " ".repeat((cols as usize).saturating_sub(42));

        println!("Progress Report for {}:", self.name);
        println!("{}", dashes);
        println!("{}", format!("      Unit        {} |       Mastery      |", dots).bold());
        
        let mut modules = units::Module::iter();
        for module in modules {
            if let Some(progress) = self.progress.get(&module) {
                self.progress.get(&module).unwrap().print_progress();
            }
        }

        // let mut sorted_progress: Vec<_> = self.progress.order();
        // // sorted_progress.sort_by_key(|(module, _)| module.to_string());
        // for (_, tracker) in sorted_progress {
        //     tracker.print_progress();
        // }
        
        println!("{}", dashes);
        
        wait_for_input();
    }

    pub fn update_progress(&mut self, unit: units::Module, question_correct: bool) {
        if let Some(tracker) = self.progress.get_mut(&unit) {
            tracker.quiz_result(question_correct);
        }
    }

}