use super::parse::*;
use super::helpers::*;
use super::print::*;
use crate::parser::interpreter::Interpreter;
use crate::Value;
use crate::modules::repl::{
    history::{load_history, save_history_line},
    autocomplete::reset_known_commands_from_interp,
    input::read_line_with_arrows,
    render::forcibly_clear_line,
};

use std::io::stdout; // Write import removed

pub fn run_repl_mode(verbose: bool) -> Result<(), String> {
    use crossterm::terminal::{disable_raw_mode, enable_raw_mode};
    use crossterm::style::Color;

    let version = env!("CARGO_PKG_VERSION");
    println!("Burn in Lava {}", version);
    enable_raw_mode().map_err(|e| format!("enable_raw_mode error: {}", e))?;
    let mut history = load_history();
    let mut interpreter = Interpreter::new();
    interpreter.set_verbose(verbose);

    crate::modules::compose::register_compose_and_pipe(&mut interpreter);
    crate::modules::sput::register_sput(&mut interpreter);
    crate::modules::slog::register_slog(&mut interpreter);
    crate::modules::ink::register_ink(&mut interpreter);
    crate::modules::include::register_include(&mut interpreter);

    reset_known_commands_from_interp(&interpreter);

    let mut partial_code = String::new();

    loop {
        let prompt_str = if partial_code.is_empty() { "> " } else { "... " };
        let user_line = match read_line_with_arrows(
            verbose,
            &mut history,
            prompt_str,
            &mut interpreter,
            &crate::modules::repl::render::redraw_full,
        ) {
            Ok(ln) => ln,
            Err(e) => {
                disable_raw_mode().ok();
                return Err(e);
            }
        };
        if partial_code.is_empty() && (user_line == ":q" || user_line == ":quit") {
            disable_raw_mode().ok();
            println!();
            interpreter.remove_all_pollers();
            return Ok(());
        }
        if user_line == "<<<EXIT>>>"
        {
            break;
        }
        save_history_line(&mut history, &user_line);
        partial_code.push_str(&user_line);
        partial_code.push('\n');
        if !is_input_complete(&partial_code) {
            continue;
        }
        let parse_result = match attempt_parse(&partial_code, verbose) {
            Ok(r) => r,
            Err(lex_msg) => {
                let mut out = stdout();
                forcibly_clear_line(&mut out)?;
                print_colored_message(&mut out, &lex_msg, Color::Red);
                partial_code.clear();
                continue;
            }
        };
        match parse_result {
            ParseResult::Incomplete => continue,
            ParseResult::Error(msg) => {
                let mut out = stdout();
                forcibly_clear_line(&mut out)?;
                print_colored_message(&mut out, &msg, Color::Red);
                partial_code.clear();
            }
            ParseResult::Success(stmts) => {
                let mut out = stdout();
                forcibly_clear_line(&mut out)?;
                let mut last_val = None;
                let mut suppress_last_val = false;
                for (_stmt_index, stmt) in stmts.iter().enumerate() {
                    let old_names: Vec<String> = interpreter
                        .get_dynamic_functions_for_clone()
                        .keys()
                        .cloned()
                        .collect();
                    let result = interpreter.exec_statement(stmt);
                    match result {
                        Ok(v) => {
                            let show_new_funcs = is_extend_or_include_call(stmt);
                            if show_new_funcs {
                                let new_names: Vec<String> = interpreter
                                    .get_dynamic_functions_for_clone()
                                    .keys()
                                    .cloned()
                                    .collect();
                                let mut newly_imported: Vec<String> = new_names
                                    .iter()
                                    .filter(|nm| !old_names.contains(nm))
                                    .cloned()
                                    .collect();
                                newly_imported.sort();
                                reset_known_commands_from_interp(&interpreter);
                                if !newly_imported.is_empty() {
                                    print_colored_message(
                                        &mut out,
                                        &crate::value_to_string(&Value::StrArray(newly_imported)),
                                        Color::DarkRed,
                                    );
                                }
                                suppress_last_val = true;
                            }
                            if is_printing_function_stmt(stmt) {
                                suppress_last_val = true;
                            }
                            if matches!(stmt, crate::parser::ast::Stmt::Assignment { .. }) {
                                reset_known_commands_from_interp(&interpreter);
                            }
                            last_val = Some(v);
                        }
                        Err(exec_err) => {
                            forcibly_clear_line(&mut out).ok();
                            print_colored_message(&mut out, &exec_err, Color::Red);
                            last_val = None;
                            break;
                        }
                    }
                }
                if let Some(val) = last_val {
                    if !suppress_last_val {
                        print_pretty_value(&mut out, &val);
                    }
                }
                partial_code.clear();
            }
        }
    }
    disable_raw_mode().ok();
    interpreter.remove_all_pollers();
    Ok(())
}
