//! Terminal banner for the `cobre` CLI.
//!
//! Color output is gated on the resolved `--color` setting (the `console` crate's
//! global stderr flag, set by `resolve_color`).
//!
//! # Example
//!
//! ```rust,no_run
//! use console::Term;
//! use cobre::banner;
//!
//! banner::print_banner(&Term::buffered_stderr());
//! ```

use console::Term;

/// Render the three-line banner as a `String`.
///
/// When `use_color` is `true`, the returned string contains ANSI 256-color
/// escape sequences. When `false`, the same Unicode characters are returned
/// without any escape codes.
pub(crate) fn render_banner_string(use_color: bool) -> String {
    let version = env!("CARGO_PKG_VERSION");

    if use_color {
        let bar = "\x1b[38;5;172m\u{257a}\u{2501}\u{2501}\u{2501}\u{2501}\u{2501}\u{2501}\u{2501}\u{2501}\u{2501}\u{257b}\x1b[0m";
        let dot = "\x1b[38;5;179m\u{25cf}\x1b[0m";
        let spark = "\x1b[38;5;214m\u{26a1}\x1b[0m";
        let cobre = format!("\x1b[1;38;5;253mCOBRE v{version}\x1b[0m");
        let tagline = "\x1b[38;5;245mPower systems in Rust\x1b[0m";
        format!(" {bar}{dot}\n {bar}{dot}{spark}  {cobre}\n {bar}{dot}   {tagline}\n")
    } else {
        let bar = "\u{257a}\u{2501}\u{2501}\u{2501}\u{2501}\u{2501}\u{2501}\u{2501}\u{2501}\u{2501}\u{257b}";
        let dot = "\u{25cf}";
        let spark = "\u{26a1}";
        format!(
            " {bar}{dot}\n {bar}{dot}{spark}  COBRE v{version}\n {bar}{dot}   Power systems in Rust\n"
        )
    }
}

/// Write the three-line Cobre banner followed by an empty line to `stderr`.
///
/// Color is enabled when [`console::colors_enabled_stderr`] returns `true` (the
/// flag `resolve_color` set from `--color`). Write errors are silently ignored;
/// the caller owns the display conditions (`--quiet`, TTY detection).
pub fn print_banner(stderr: &Term) {
    let use_color = console::colors_enabled_stderr();
    let banner = render_banner_string(use_color);
    for line in banner.lines() {
        let _ = stderr.write_line(line);
    }
    let _ = stderr.write_line("");
}

#[cfg(test)]
mod tests {
    use console::Term;

    use super::{print_banner, render_banner_string};

    #[test]
    fn test_render_banner_colored_contains_ansi_escapes() {
        let banner = render_banner_string(true);
        assert!(banner.contains("\x1b[38;5;172m"));
        assert!(banner.contains("\x1b[0m"));
    }

    #[test]
    fn test_render_banner_plain_no_ansi_escapes() {
        let banner = render_banner_string(false);
        assert!(!banner.contains("\x1b["));
    }

    #[test]
    fn test_render_banner_contains_version() {
        let banner = render_banner_string(false);
        let idx = banner
            .find("COBRE v")
            .expect("banner must contain 'COBRE v'");
        let after = &banner[idx + "COBRE v".len()..];
        assert!(after.chars().next().is_some_and(|c| c.is_ascii_digit()));
    }

    #[test]
    fn test_render_banner_contains_unicode_busbars() {
        let banner = render_banner_string(false);
        assert!(banner.contains('\u{2501}'));
        assert!(banner.contains('\u{25cf}'));
    }

    #[test]
    fn test_print_banner_does_not_panic() {
        print_banner(&Term::buffered_stderr());
    }
}
