#[allow(unused_imports)] // get_panic_log_file_message is behind feature "write_panic_log".
use std::{
    backtrace::Backtrace,
    io::{self, Write},
    panic::PanicInfo,
};

#[cfg(feature = "colored_panic_message")]
use console::style;

pub fn get_message(panicinfo: &PanicInfo) -> String {
    let mut panic_location: String = "Could not get panic location.".to_string();
    let panic_payload: String = panic_message::panic_info_message(panicinfo).to_string();

    if let Some(location) = panicinfo.location() {
        panic_location = format!(
            "{}:{}:{}",
            location.file(),
            location.line(),
            location.column()
        );
    }

    format!(
        "\n\nThe current process panicked!\n\nPanic location: {panic_location}\nPanic payload: {panic_payload}\n\n\n",
    )
}

#[cfg(feature = "colored_panic_message")]
fn get_colorful_panic_message(panicinfo: &PanicInfo) -> String {
    let mut panic_location = style("Could not get panic location.".to_string()).blue();
    let panic_payload = style(panic_message::panic_info_message(panicinfo).to_string()).yellow();

    if let Some(location) = panicinfo.location() {
        panic_location = style(format!(
            "\"{}:{}:{}\"",
            location.file(),
            location.line(),
            location.column()
        ))
        .blue();
    }

    format!(
        "\n\n{}\n\nPanic location: {panic_location}\nPanic payload: {panic_payload}\n\n\n",
        style("The current process panicked!").red()
    )
}

pub fn log_message(panicinfo: &PanicInfo) -> Result<(), std::io::Error> {
    // Prints the panic information.
    let stderr: io::Stderr = io::stderr();
    let mut handle: io::StderrLock<'_> = stderr.lock();

    // Looks awful but its the only way i could get it working.
    // TODO: Clean up this mess.
    // Disabling the clippy late init lint becouse i can't find another way that works.
    #[allow(clippy::needless_late_init)]
    let stderr_write_status: Result<(), std::io::Error>;
    cfg_if::cfg_if! {
        if #[cfg(feature = "colored_panic_message")] {
            if console::colors_enabled_stderr() {
                let made_panic_message = get_colorful_panic_message(panicinfo);
                stderr_write_status = handle.write_all(&made_panic_message.into_bytes());
            } else {
                let made_panic_message = get_message(panicinfo);
                stderr_write_status = handle.write_all(&made_panic_message.into_bytes());
            }
        } else {
            let made_panic_message = get_message(panicinfo);
            stderr_write_status = handle.write_all(&made_panic_message.into_bytes());
        }
    }

    stderr_write_status
}

#[cfg(feature = "write_panic_log")]
pub fn get_panic_log_file_message(
    panicinfo: &PanicInfo,
    system_info: &str,
    captured_backtrace: Option<Backtrace>,
) -> String {
    let panic_message: String = get_message(panicinfo);
    let panic_backtrace: String = match captured_backtrace {
        Some(bt) => format!("{bt}"),
        None => "No backtrace captured.".to_string(),
    };

    // ABSOLUTELY BEAUTIFUL CODE RIGHT HERE!!!!!
    format!(
        "##### PANIC MESSAGE #####{panic_message}\n{system_info}\n\n##### CAPTURED BACKTRACE #####\n\n{panic_backtrace}",
    )
}

pub fn print_debug_info(_message: &str) {
    #[cfg(feature = "debug_messages")]
    println!("{}", _message);
}
