use crate::color::perceptual_distance;
use codex_terminal_detection::TerminalName;
use codex_terminal_detection::terminal_info;
use ratatui::style::Color;

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum StdoutColorLevel {
    TrueColor,
    Ansi256,
    Ansi16,
    Unknown,
}

pub fn stdout_color_level() -> StdoutColorLevel {
    match supports_color::on_cached(supports_color::Stream::Stdout) {
        Some(level) if level.has_16m => StdoutColorLevel::TrueColor,
        Some(level) if level.has_256 => StdoutColorLevel::Ansi256,
        Some(_) => StdoutColorLevel::Ansi16,
        None => StdoutColorLevel::Unknown,
    }
}

#[allow(clippy::disallowed_methods)]
pub fn rgb_color((r, g, b): (u8, u8, u8)) -> Color {
    Color::Rgb(r, g, b)
}

#[allow(clippy::disallowed_methods)]
pub fn indexed_color(index: u8) -> Color {
    Color::Indexed(index)
}

/// Returns the closest color to the target color that the terminal can display.
pub fn best_color(target: (u8, u8, u8)) -> Color {
    best_color_for_color_level(target, effective_stdout_color_level())
}

/// Returns the closest color to the target color for a known terminal color level.
pub fn best_color_for_level(target: (u8, u8, u8), color_level: StdoutColorLevel) -> Color {
    best_color_for_color_level(target, color_level)
}

fn effective_stdout_color_level() -> StdoutColorLevel {
    stdout_color_level_for_terminal(
        stdout_color_level(),
        terminal_info().name,
        std::env::var_os("WT_SESSION").is_some(),
        std::env::var_os("FORCE_COLOR").is_some(),
    )
}

fn stdout_color_level_for_terminal(
    stdout_level: StdoutColorLevel,
    terminal_name: TerminalName,
    has_wt_session: bool,
    has_force_color_override: bool,
) -> StdoutColorLevel {
    if has_wt_session && !has_force_color_override {
        return StdoutColorLevel::TrueColor;
    }

    if stdout_level == StdoutColorLevel::Ansi16
        && terminal_name == TerminalName::WindowsTerminal
        && !has_force_color_override
    {
        StdoutColorLevel::TrueColor
    } else {
        stdout_level
    }
}

fn best_color_for_color_level(target: (u8, u8, u8), color_level: StdoutColorLevel) -> Color {
    match color_level {
        StdoutColorLevel::TrueColor => rgb_color(target),
        StdoutColorLevel::Ansi256 => xterm_fixed_colors()
            .min_by(|(_, a), (_, b)| {
                perceptual_distance(*a, target)
                    .partial_cmp(&perceptual_distance(*b, target))
                    .unwrap_or(std::cmp::Ordering::Equal)
            })
            .map_or_else(Color::default, |(i, _)| indexed_color(i as u8)),
        StdoutColorLevel::Ansi16 | StdoutColorLevel::Unknown => Color::default(),
    }
}

pub fn requery_default_colors() {
    imp::requery_default_colors();
}

#[derive(Clone, Copy)]
pub struct DefaultColors {
    fg: (u8, u8, u8),
    bg: (u8, u8, u8),
}

pub fn default_colors() -> Option<DefaultColors> {
    imp::default_colors()
}

pub fn default_fg() -> Option<(u8, u8, u8)> {
    default_colors().map(|c| c.fg)
}

pub fn default_bg() -> Option<(u8, u8, u8)> {
    default_colors().map(|c| c.bg)
}

#[cfg(any(unix, windows))]
pub(crate) fn set_default_colors_from_startup_probe(
    colors: Option<crate::terminal_probe::DefaultColors>,
) {
    imp::set_default_colors_from_startup_probe(colors);
}

#[cfg(all(unix, not(test)))]
mod imp {
    use super::DefaultColors;
    use crossterm::style::Color as CrosstermColor;
    use crossterm::style::query_background_color;
    use crossterm::style::query_foreground_color;
    use std::sync::Mutex;
    use std::sync::OnceLock;

    struct Cache<T> {
        attempted: bool,
        value: Option<T>,
    }

    impl<T> Default for Cache<T> {
        fn default() -> Self {
            Self {
                attempted: false,
                value: None,
            }
        }
    }

    impl<T: Copy> Cache<T> {
        fn get_or_init_with(&mut self, mut init: impl FnMut() -> Option<T>) -> Option<T> {
            if !self.attempted {
                self.value = init();
                self.attempted = true;
            }
            self.value
        }
    }

    fn default_colors_cache() -> &'static Mutex<Cache<DefaultColors>> {
        static CACHE: OnceLock<Mutex<Cache<DefaultColors>>> = OnceLock::new();
        CACHE.get_or_init(|| Mutex::new(Cache::default()))
    }

    pub(super) fn default_colors() -> Option<DefaultColors> {
        let cache = default_colors_cache();
        let mut cache = cache.lock().ok()?;
        cache.get_or_init_with(query_default_colors)
    }

    pub(super) fn set_default_colors_from_startup_probe(
        colors: Option<crate::terminal_probe::DefaultColors>,
    ) {
        if let Ok(mut cache) = default_colors_cache().lock() {
            cache.value = colors.map(|colors| DefaultColors {
                fg: colors.fg,
                bg: colors.bg,
            });
            cache.attempted = true;
        }
    }

    pub(super) fn requery_default_colors() {
        if let Ok(mut cache) = default_colors_cache().lock() {
            // Don't try to refresh if the cache is already attempted and failed.
            if cache.attempted && cache.value.is_none() {
                return;
            }

            // Focus events arrive after crossterm's event stream is active. Requery through
            // crossterm here so unrelated input stays in crossterm's skipped-event queue instead
            // of being consumed by the bounded startup probe's direct tty reads.
            let fg = query_foreground_color()
                .ok()
                .flatten()
                .and_then(color_to_tuple);
            let bg = query_background_color()
                .ok()
                .flatten()
                .and_then(color_to_tuple);
            cache.value = fg.zip(bg).map(|(fg, bg)| DefaultColors { fg, bg });
            cache.attempted = true;
        }
    }

    /// Queries terminal default colors through the bounded startup probe path.
    ///
    /// The palette cache treats `None` as an attempted-but-unavailable result, so this function
    /// collapses I/O errors and missing responses into the same fallback path used for terminals
    /// that simply do not support OSC 10/11 queries.
    fn query_default_colors() -> Option<DefaultColors> {
        crate::terminal_probe::default_colors(crate::terminal_probe::DEFAULT_TIMEOUT)
            .ok()
            .flatten()
            .map(|colors| DefaultColors {
                fg: colors.fg,
                bg: colors.bg,
            })
    }

    fn color_to_tuple(color: CrosstermColor) -> Option<(u8, u8, u8)> {
        match color {
            CrosstermColor::Rgb { r, g, b } => Some((r, g, b)),
            _ => None,
        }
    }
}

#[cfg(windows)]
mod imp {
    use super::DefaultColors;
    use std::sync::Mutex;
    use std::sync::OnceLock;

    struct Cache<T> {
        attempted: bool,
        value: Option<T>,
    }

    impl<T> Default for Cache<T> {
        fn default() -> Self {
            Self {
                attempted: false,
                value: None,
            }
        }
    }

    impl<T: Copy> Cache<T> {
        fn get_or_init_with(&mut self, mut init: impl FnMut() -> Option<T>) -> Option<T> {
            if !self.attempted {
                self.value = init();
                self.attempted = true;
            }
            self.value
        }
    }

    fn default_colors_cache() -> &'static Mutex<Cache<DefaultColors>> {
        static CACHE: OnceLock<Mutex<Cache<DefaultColors>>> = OnceLock::new();
        CACHE.get_or_init(|| Mutex::new(Cache::default()))
    }

    pub(super) fn default_colors() -> Option<DefaultColors> {
        let cache = default_colors_cache();
        let mut cache = cache.lock().ok()?;
        cache.get_or_init_with(query_default_colors)
    }

    pub(super) fn set_default_colors_from_startup_probe(
        colors: Option<crate::terminal_probe::DefaultColors>,
    ) {
        if let Ok(mut cache) = default_colors_cache().lock() {
            cache.value = colors.map(|colors| DefaultColors {
                fg: colors.fg,
                bg: colors.bg,
            });
            cache.attempted = true;
        }
    }

    pub(super) fn requery_default_colors() {}

    fn query_default_colors() -> Option<DefaultColors> {
        crate::terminal_probe::default_colors(crate::terminal_probe::DEFAULT_TIMEOUT)
            .ok()
            .flatten()
            .map(|colors| DefaultColors {
                fg: colors.fg,
                bg: colors.bg,
            })
    }
}

#[cfg(not(any(all(unix, not(test)), windows)))]
mod imp {
    use super::DefaultColors;

    pub(super) fn default_colors() -> Option<DefaultColors> {
        None
    }

    #[cfg(any(unix, windows))]
    pub(super) fn set_default_colors_from_startup_probe(
        _colors: Option<crate::terminal_probe::DefaultColors>,
    ) {
    }

    pub(super) fn requery_default_colors() {}
}

/// The subset of Xterm colors that are usually consistent across terminals.
fn xterm_fixed_colors() -> impl Iterator<Item = (usize, (u8, u8, u8))> {
    XTERM_COLORS.into_iter().enumerate().skip(16)
}

// Xterm colors; derived from https://ss64.com/bash/syntax-colors.html
pub const XTERM_COLORS: [(u8, u8, u8); 256] = [
    // The first 16 colors vary based on terminal theme, so these are likely not the actual colors
    // that are displayed when using these indices.
    (0, 0, 0),       //   0 Black (SYSTEM)
    (128, 0, 0),     //   1 Maroon (SYSTEM)
    (0, 128, 0),     //   2 Green (SYSTEM)
    (128, 128, 0),   //   3 Olive (SYSTEM)
    (0, 0, 128),     //   4 Navy (SYSTEM)
    (128, 0, 128),   //   5 Purple (SYSTEM)
    (0, 128, 128),   //   6 Teal (SYSTEM)
    (192, 192, 192), //   7 Silver (SYSTEM)
    (128, 128, 128), //   8 Grey (SYSTEM)
    (255, 0, 0),     //   9 Red (SYSTEM)
    (0, 255, 0),     //  10 Lime (SYSTEM)
    (255, 255, 0),   //  11 Yellow (SYSTEM)
    (0, 0, 255),     //  12 Blue (SYSTEM)
    (255, 0, 255),   //  13 Fuchsia (SYSTEM)
    (0, 255, 255),   //  14 Aqua (SYSTEM)
    (255, 255, 255), //  15 White (SYSTEM)
    // The rest of the colors are consistent in most terminals.
    (0, 0, 0),       //  16 Grey0
    (0, 0, 95),      //  17 NavyBlue
    (0, 0, 135),     //  18 DarkBlue
    (0, 0, 175),     //  19 Blue3
    (0, 0, 215),     //  20 Blue3
    (0, 0, 255),     //  21 Blue1
    (0, 95, 0),      //  22 DarkGreen
    (0, 95, 95),     //  23 DeepSkyBlue4
    (0, 95, 135),    //  24 DeepSkyBlue4
    (0, 95, 175),    //  25 DeepSkyBlue4
    (0, 95, 215),    //  26 DodgerBlue3
    (0, 95, 255),    //  27 DodgerBlue2
    (0, 135, 0),     //  28 Green4
    (0, 135, 95),    //  29 SpringGreen4
    (0, 135, 135),   //  30 Turquoise4
    (0, 135, 175),   //  31 DeepSkyBlue3
    (0, 135, 215),   //  32 DeepSkyBlue3
    (0, 135, 255),   //  33 DodgerBlue1
    (0, 175, 0),     //  34 Green3
    (0, 175, 95),    //  35 SpringGreen3
    (0, 175, 135),   //  36 DarkCyan
    (0, 175, 175),   //  37 LightSeaGreen
    (0, 175, 215),   //  38 DeepSkyBlue2
    (0, 175, 255),   //  39 DeepSkyBlue1
    (0, 215, 0),     //  40 Green3
    (0, 215, 95),    //  41 SpringGreen3
    (0, 215, 135),   //  42 SpringGreen2
    (0, 215, 175),   //  43 Cyan3
    (0, 215, 215),   //  44 DarkTurquoise
    (0, 215, 255),   //  45 Turquoise2
    (0, 255, 0),     //  46 Green1
    (0, 255, 95),    //  47 SpringGreen2
    (0, 255, 135),   //  48 SpringGreen1
    (0, 255, 175),   //  49 MediumSpringGreen
    (0, 255, 215),   //  50 Cyan2
    (0, 255, 255),   //  51 Cyan1
    (95, 0, 0),      //  52 DarkRed
    (95, 0, 95),     //  53 DeepPink4
    (95, 0, 135),    //  54 Purple4
    (95, 0, 175),    //  55 Purple4
    (95, 0, 215),    //  56 Purple3
    (95, 0, 255),    //  57 BlueViolet
    (95, 95, 0),     //  58 Orange4
    (95, 95, 95),    //  59 Grey37
    (95, 95, 135),   //  60 MediumPurple4
    (95, 95, 175),   //  61 SlateBlue3
    (95, 95, 215),   //  62 SlateBlue3
    (95, 95, 255),   //  63 RoyalBlue1
    (95, 135, 0),    //  64 Chartreuse4
    (95, 135, 95),   //  65 DarkSeaGreen4
    (95, 135, 135),  //  66 PaleTurquoise4
    (95, 135, 175),  //  67 SteelBlue
    (95, 135, 215),  //  68 SteelBlue3
    (95, 135, 255),  //  69 CornflowerBlue
    (95, 175, 0),    //  70 Chartreuse3
    (95, 175, 95),   //  71 DarkSeaGreen4
    (95, 175, 135),  //  72 CadetBlue
    (95, 175, 175),  //  73 CadetBlue
    (95, 175, 215),  //  74 SkyBlue3
    (95, 175, 255),  //  75 SteelBlue1
    (95, 215, 0),    //  76 Chartreuse3
    (95, 215, 95),   //  77 PaleGreen3
    (95, 215, 135),  //  78 SeaGreen3
    (95, 215, 175),  //  79 Aquamarine3
    (95, 215, 215),  //  80 MediumTurquoise
    (95, 215, 255),  //  81 SteelBlue1
    (95, 255, 0),    //  82 Chartreuse2
    (95, 255, 95),   //  83 SeaGreen2
    (95, 255, 135),  //  84 SeaGreen1
    (95, 255, 175),  //  85 SeaGreen1
    (95, 255, 215),  //  86 Aquamarine1
    (95, 255, 255),  //  87 DarkSlateGray2
    (135, 0, 0),     //  88 DarkRed
    (135, 0, 95),    //  89 DeepPink4
    (135, 0, 135),   //  90 DarkMagenta
    (135, 0, 175),   //  91 DarkMagenta
    (135, 0, 215),   //  92 DarkViolet
    (135, 0, 255),   //  93 Purple
    (135, 95, 0),    //  94 Orange4
    (135, 95, 95),   //  95 LightPink4
    (135, 95, 135),  //  96 Plum4
    (135, 95, 175),  //  97 MediumPurple3
    (135, 95, 215),  //  98 MediumPurple3
    (135, 95, 255),  //  99 SlateBlue1
    (135, 135, 0),   // 100 Yellow4
    (135, 135, 95),  // 101 Wheat4
    (135, 135, 135), // 102 Grey53
    (135, 135, 175), // 103 LightSlateGrey
    (135, 135, 215), // 104 MediumPurple
    (135, 135, 255), // 105 LightSlateBlue
    (135, 175, 0),   // 106 Yellow4
    (135, 175, 95),  // 107 DarkOliveGreen3
    (135, 175, 135), // 108 DarkSeaGreen
    (135, 175, 175), // 109 LightSkyBlue3
    (135, 175, 215), // 110 LightSkyBlue3
    (135, 175, 255), // 111 SkyBlue2
    (135, 215, 0),   // 112 Chartreuse2
    (135, 215, 95),  // 113 DarkOliveGreen3
    (135, 215, 135), // 114 PaleGreen3
    (135, 215, 175), // 115 DarkSeaGreen3
    (135, 215, 215), // 116 DarkSlateGray3
    (135, 215, 255), // 117 SkyBlue1
    (135, 255, 0),   // 118 Chartreuse1
    (135, 255, 95),  // 119 LightGreen
    (135, 255, 135), // 120 LightGreen
    (135, 255, 175), // 121 PaleGreen1
    (135, 255, 215), // 122 Aquamarine1
    (135, 255, 255), // 123 DarkSlateGray1
    (175, 0, 0),     // 124 Red3
    (175, 0, 95),    // 125 DeepPink4
    (175, 0, 135),   // 126 MediumVioletRed
    (175, 0, 175),   // 127 Magenta3
    (175, 0, 215),   // 128 DarkViolet
    (175, 0, 255),   // 129 Purple
    (175, 95, 0),    // 130 DarkOrange3
    (175, 95, 95),   // 131 IndianRed
    (175, 95, 135),  // 132 HotPink3
    (175, 95, 175),  // 133 MediumOrchid3
    (175, 95, 215),  // 134 MediumOrchid
    (175, 95, 255),  // 135 MediumPurple2
    (175, 135, 0),   // 136 DarkGoldenrod
    (175, 135, 95),  // 137 LightSalmon3
    (175, 135, 135), // 138 RosyBrown
    (175, 135, 175), // 139 Grey63
    (175, 135, 215), // 140 MediumPurple2
    (175, 135, 255), // 141 MediumPurple1
    (175, 175, 0),   // 142 Gold3
    (175, 175, 95),  // 143 DarkKhaki
    (175, 175, 135), // 144 NavajoWhite3
    (175, 175, 175), // 145 Grey69
    (175, 175, 215), // 146 LightSteelBlue3
    (175, 175, 255), // 147 LightSteelBlue
    (175, 215, 0),   // 148 Yellow3
    (175, 215, 95),  // 149 DarkOliveGreen3
    (175, 215, 135), // 150 DarkSeaGreen3
    (175, 215, 175), // 151 DarkSeaGreen2
    (175, 215, 215), // 152 LightCyan3
    (175, 215, 255), // 153 LightSkyBlue1
    (175, 255, 0),   // 154 GreenYellow
    (175, 255, 95),  // 155 DarkOliveGreen2
    (175, 255, 135), // 156 PaleGreen1
    (175, 255, 175), // 157 DarkSeaGreen2
    (175, 255, 215), // 158 DarkSeaGreen1
    (175, 255, 255), // 159 PaleTurquoise1
    (215, 0, 0),     // 160 Red3
    (215, 0, 95),    // 161 DeepPink3
    (215, 0, 135),   // 162 DeepPink3
    (215, 0, 175),   // 163 Magenta3
    (215, 0, 215),   // 164 Magenta3
    (215, 0, 255),   // 165 Magenta2
    (215, 95, 0),    // 166 DarkOrange3
    (215, 95, 95),   // 167 IndianRed
    (215, 95, 135),  // 168 HotPink3
    (215, 95, 175),  // 169 HotPink2
    (215, 95, 215),  // 170 Orchid
    (215, 95, 255),  // 171 MediumOrchid1
    (215, 135, 0),   // 172 Orange3
    (215, 135, 95),  // 173 LightSalmon3
    (215, 135, 135), // 174 LightPink3
    (215, 135, 175), // 175 Pink3
    (215, 135, 215), // 176 Plum3
    (215, 135, 255), // 177 Violet
    (215, 175, 0),   // 178 Gold3
    (215, 175, 95),  // 179 LightGoldenrod3
    (215, 175, 135), // 180 Tan
    (215, 175, 175), // 181 MistyRose3
    (215, 175, 215), // 182 Thistle3
    (215, 175, 255), // 183 Plum2
    (215, 215, 0),   // 184 Yellow3
    (215, 215, 95),  // 185 Khaki3
    (215, 215, 135), // 186 LightGoldenrod2
    (215, 215, 175), // 187 LightYellow3
    (215, 215, 215), // 188 Grey84
    (215, 215, 255), // 189 LightSteelBlue1
    (215, 255, 0),   // 190 Yellow2
    (215, 255, 95),  // 191 DarkOliveGreen1
    (215, 255, 135), // 192 DarkOliveGreen1
    (215, 255, 175), // 193 DarkSeaGreen1
    (215, 255, 215), // 194 Honeydew2
    (215, 255, 255), // 195 LightCyan1
    (255, 0, 0),     // 196 Red1
    (255, 0, 95),    // 197 DeepPink2
    (255, 0, 135),   // 198 DeepPink1
    (255, 0, 175),   // 199 DeepPink1
    (255, 0, 215),   // 200 Magenta2
    (255, 0, 255),   // 201 Magenta1
    (255, 95, 0),    // 202 OrangeRed1
    (255, 95, 95),   // 203 IndianRed1
    (255, 95, 135),  // 204 IndianRed1
    (255, 95, 175),  // 205 HotPink
    (255, 95, 215),  // 206 HotPink
    (255, 95, 255),  // 207 MediumOrchid1
    (255, 135, 0),   // 208 DarkOrange
    (255, 135, 95),  // 209 Salmon1
    (255, 135, 135), // 210 LightCoral
    (255, 135, 175), // 211 PaleVioletRed1
    (255, 135, 215), // 212 Orchid2
    (255, 135, 255), // 213 Orchid1
    (255, 175, 0),   // 214 Orange1
    (255, 175, 95),  // 215 SandyBrown
    (255, 175, 135), // 216 LightSalmon1
    (255, 175, 175), // 217 LightPink1
    (255, 175, 215), // 218 Pink1
    (255, 175, 255), // 219 Plum1
    (255, 215, 0),   // 220 Gold1
    (255, 215, 95),  // 221 LightGoldenrod2
    (255, 215, 135), // 222 LightGoldenrod2
    (255, 215, 175), // 223 NavajoWhite1
    (255, 215, 215), // 224 MistyRose1
    (255, 215, 255), // 225 Thistle1
    (255, 255, 0),   // 226 Yellow1
    (255, 255, 95),  // 227 LightGoldenrod1
    (255, 255, 135), // 228 Khaki1
    (255, 255, 175), // 229 Wheat1
    (255, 255, 215), // 230 Cornsilk1
    (255, 255, 255), // 231 Grey100
    (8, 8, 8),       // 232 Grey3
    (18, 18, 18),    // 233 Grey7
    (28, 28, 28),    // 234 Grey11
    (38, 38, 38),    // 235 Grey15
    (48, 48, 48),    // 236 Grey19
    (58, 58, 58),    // 237 Grey23
    (68, 68, 68),    // 238 Grey27
    (78, 78, 78),    // 239 Grey30
    (88, 88, 88),    // 240 Grey35
    (98, 98, 98),    // 241 Grey39
    (108, 108, 108), // 242 Grey42
    (118, 118, 118), // 243 Grey46
    (128, 128, 128), // 244 Grey50
    (138, 138, 138), // 245 Grey54
    (148, 148, 148), // 246 Grey58
    (158, 158, 158), // 247 Grey62
    (168, 168, 168), // 248 Grey66
    (178, 178, 178), // 249 Grey70
    (188, 188, 188), // 250 Grey74
    (198, 198, 198), // 251 Grey78
    (208, 208, 208), // 252 Grey82
    (218, 218, 218), // 253 Grey85
    (228, 228, 228), // 254 Grey89
    (238, 238, 238), // 255 Grey93
];

#[cfg(test)]
mod tests {
    use super::*;
    use pretty_assertions::assert_eq;

    #[test]
    fn best_color_uses_truecolor_without_quantization() {
        assert_eq!(
            best_color_for_color_level((12, 34, 56), StdoutColorLevel::TrueColor),
            rgb_color((12, 34, 56))
        );
    }

    #[test]
    fn best_color_resets_for_ansi16() {
        assert_eq!(
            best_color_for_color_level((12, 34, 56), StdoutColorLevel::Ansi16),
            Color::Reset
        );
    }

    #[test]
    fn windows_terminal_wt_session_promotes_to_truecolor() {
        assert_eq!(
            stdout_color_level_for_terminal(
                StdoutColorLevel::Ansi16,
                TerminalName::Unknown,
                /*has_wt_session*/ true,
                /*has_force_color_override*/ false,
            ),
            StdoutColorLevel::TrueColor
        );
    }

    #[test]
    fn windows_terminal_name_promotes_ansi16_to_truecolor() {
        assert_eq!(
            stdout_color_level_for_terminal(
                StdoutColorLevel::Ansi16,
                TerminalName::WindowsTerminal,
                /*has_wt_session*/ false,
                /*has_force_color_override*/ false,
            ),
            StdoutColorLevel::TrueColor
        );
    }

    #[test]
    fn force_color_keeps_reported_stdout_level() {
        assert_eq!(
            stdout_color_level_for_terminal(
                StdoutColorLevel::Ansi16,
                TerminalName::WindowsTerminal,
                /*has_wt_session*/ true,
                /*has_force_color_override*/ true,
            ),
            StdoutColorLevel::Ansi16
        );
    }
}
