use crossterm::{execute, style::Stylize, terminal::{size, Clear, ClearType}};
use std::io::stdout;

// const DELAY_SECONDS: u64 = 1;

#[derive(PartialEq)]
pub enum StatementType {
    Default,
    // DelayExplanation,
    Question,
    GeneralFeedback,
    CorrectFeedback,
    IncorrectFeedback,
}

/// Clear the console
pub fn clear_console() {
    execute!(stdout(), Clear(ClearType::All)).unwrap();
}

/// Pretty-print an instruction centered on the screen in an outlined box
pub fn print_boxed(instruction: &str, statement_type: StatementType) {
    let (cols, rows) = size().unwrap();
    let padding = 4;
    let max_width = 100;
    let instruction = instruction
        .lines()
        .flat_map(|line| {
            let mut split_lines = vec![];
            let mut current_line = String::new();
            for word in line.split_whitespace() {
                let word_width = word.chars().map(|c| if c.len_utf8() > 1 { 2 } else { 1 }).sum::<usize>();
                if current_line.chars().map(|c| if c.len_utf8() > 1 { 2 } else { 1 }).sum::<usize>() + word_width + 1 > std::cmp::min(max_width, cols as usize) {
                    split_lines.push(current_line.trim_end().to_string());
                    current_line = String::new();
                }
                current_line.push_str(word);
                current_line.push(' ');
            }
            if !current_line.is_empty() {
                split_lines.push(current_line.trim_end().to_string());
            }
            split_lines
        })
        .collect::<Vec<_>>()
        .join("\n");
    let box_width = std::cmp::min(
        instruction.lines().map(|line| line.chars().map(|c| c.len_utf8()).sum::<usize>()).max().unwrap_or(0) + padding * 2,
        max_width,
    );
    let box_height = instruction.lines().count() + 2;

    let start_col = (cols.saturating_sub(box_width as u16)) / 2;
    let start_row = (rows.saturating_sub(box_height as u16)) / 2;

    let top_border;
    let bottom_border;
    let empty_line;

    match statement_type {
        StatementType::Question => {
            top_border = format!("{}{}{}", "┌".dark_blue(), "─".repeat(box_width).dark_blue(), "┐".dark_blue());
            bottom_border = format!("{}{}{}", "└".dark_blue(), "─".repeat(box_width).dark_blue(), "┘".dark_blue());
            empty_line = format!("{}{}{}", "│".dark_blue(), " ".repeat(box_width).dark_blue(), "│".dark_blue());
        }
        StatementType::GeneralFeedback => {
            top_border = format!("{}{}{}", "┌".dark_magenta(), "─".repeat(box_width).dark_magenta(), "┐".dark_magenta());
            bottom_border = format!("{}{}{}", "└".dark_magenta(), "─".repeat(box_width).dark_magenta(), "┘".dark_magenta());
            empty_line = format!("{}{}{}", "│".dark_magenta(), " ".repeat(box_width).dark_magenta(), "│".dark_magenta());
        }
        StatementType::CorrectFeedback => {
            top_border = format!("{}{}{}", "┌".green(), "─".repeat(box_width).green(), "┐".green());
            bottom_border = format!("{}{}{}", "└".green(), "─".repeat(box_width).green(), "┘".green());
            empty_line = format!("{}{}{}", "│".green(), " ".repeat(box_width).green(), "│".green());
        }
        StatementType::IncorrectFeedback => {
            top_border = format!("{}{}{}", "┌".red(), "─".repeat(box_width).red(), "┐".red());
            bottom_border = format!("{}{}{}", "└".red(), "─".repeat(box_width).red(), "┘".red());
            empty_line = format!("{}{}{}", "│".red(), " ".repeat(box_width).red(), "│".red());
        }
        _ => {
            top_border = format!("┌{}┐", "─".repeat(box_width));
            bottom_border = format!("└{}┘", "─".repeat(box_width));
            empty_line = format!("│{}│", " ".repeat(box_width));
        }
    }

    clear_console();

    for i in 0..box_height {
        let line = match i {
            0 => &top_border,
            i if i == box_height - 1 => &bottom_border,
            i if i > 0 && i < box_height - 1 => {
                let line_content = instruction
                    .lines()
                    .nth(i - 1)
                    .unwrap_or("")
                    .trim();
                let line_width = line_content.chars().map(|c| if c.len_utf8() > 1 { 2 } else { 1 }).sum::<usize>();
                match statement_type {
                    StatementType::Question => {
                        &format!(
                            "{}{}{}{}{}",
                            "│".dark_blue(),
                            " ".repeat((box_width.saturating_sub(line_width)) / 2),
                            line_content,
                            " ".repeat((box_width.saturating_sub(line_width) + 1) / 2),
                            "│".dark_blue(),
                        )
                    }
                    StatementType::GeneralFeedback => {
                        &format!(
                            "{}{}{}{}{}",
                            "│".dark_magenta(),
                            " ".repeat((box_width.saturating_sub(line_width)) / 2),
                            line_content,
                            " ".repeat((box_width.saturating_sub(line_width) + 1) / 2),
                            "│".dark_magenta(),
                        )
                    }
                    StatementType::CorrectFeedback => {
                        &format!(
                            "{}{}{}{}{}",
                            "│".green(),
                            " ".repeat((box_width.saturating_sub(line_width)) / 2),
                            line_content,
                            " ".repeat((box_width.saturating_sub(line_width) + 1) / 2),
                            "│".green(),
                        )
                    }
                    StatementType::IncorrectFeedback => {
                        &format!(
                            "{}{}{}{}{}",
                            "│".red(),
                            " ".repeat((box_width.saturating_sub(line_width)) / 2),
                            line_content,
                            " ".repeat((box_width.saturating_sub(line_width) + 1) / 2),
                            "│".red(),
                        )
                    }
                    _ => {
                        &format!(
                            "│{}{}{}│",
                            " ".repeat((box_width.saturating_sub(line_width)) / 2),
                            line_content,
                            " ".repeat((box_width.saturating_sub(line_width) + 1) / 2),
                        )
                    }
                }
            }
            _ => &empty_line,
        };
        println!("\x1B[{};{}H{}", start_row + i as u16, start_col + 1, line);
    }

    match statement_type {
        StatementType::Question => {
            return;
        }
        _ => {
            wait_for_input();
        }
    }
}

/// Prints a full-width ruler of designated characters
// pub fn print_rule(character: char, padding: (bool, bool)) {
//     let (cols, _) = size().unwrap();

//     println!(
//         "{}{}{}",
//         if padding.0 { "\n" } else { "" },
//         character.to_string().repeat(cols as usize),
//         if padding.1 { "\n" } else { "" }
//     );
// }

/// Horizontally center the desired text on the screen
// pub fn print_centered(text: &str) {
//     let (cols, _) = size().unwrap();
//     let text_width = text.len() as u16;
//     let start_col = (cols.saturating_sub(text_width)) / 2;

//     println!(
//         "\x1B[{}C{}",
//         start_col,
//         text
//     );
// }

/// Wait for input from the user
pub fn wait_for_input() {
    let prompt = "Press enter to continue";
    let (cols, _) = size().unwrap();
    let text_width = prompt.len() as u16;
    let start_col = (cols.saturating_sub(text_width)) / 2 + 1;

    println!(
        "\x1B[{}C{}",
        start_col,
        prompt.italic().dark_blue()
    );

    // println!("{}", prompt.italic().dark_blue());
    crossterm::event::read().unwrap();
}

/// Wait for input from the user
// pub fn print_title(title: &str) {
//     let (cols, _) = size().unwrap();
//     let text_width = title.len() as u16;
//     let start_col = (cols.saturating_sub(text_width)) / 2 + 1;

//     println!(
//         "\x1B[{}C{}",
//         start_col,
//         title.bold()
//     );

//     wait_for_input();
// }

/// Wait for input from the user
// pub fn wait_for_input_delay(seconds: u64) {
//     let prompt = format!("Remember to be mindful. Advance in {} seconds.", seconds);
//     let (cols, _) = size().unwrap();
//     let text_width = prompt.len() as u16;
//     let start_col = (cols.saturating_sub(text_width)) / 2 + 1;

//     println!(
//         "\x1B[{}C{}",
//         start_col,
//         prompt.italic().dark_blue()
//     );

//     std::thread::sleep(std::time::Duration::from_secs(DELAY_SECONDS));

// }

/// Wait for input from the user
// pub fn inform_delay(seconds: u64) {
//     let prompt = format!("Remember to be mindful. Answers appear in {} seconds.", seconds);
//     let (cols, _) = size().unwrap();
//     let text_width = prompt.len() as u16;
//     let start_col = (cols.saturating_sub(text_width)) / 2 + 1;

//     println!(
//         "\x1B[{}C{}",
//         start_col,
//         prompt.italic().dark_blue()
//     );

// }

pub fn unit_screen(title: &str) {
    clear_console();
    print_boxed(title, StatementType::GeneralFeedback);
    // print_boxed(&format!("{}", description), StatementType::Default);
}

pub fn print_screen(text: &str) {
    clear_console();
    print_boxed(text, StatementType::Default);
}