use std::{
    io::{self, Write},
    sync::Arc,
};
use misykat::{jiff::civil, salah::PrayerTimes};
use owo_colors::{OwoColorize, Stream::Stdout};
use crate::{
    cli::Opts,
    config::{Config, TimeFormat},
};
#[derive(Debug)]
pub struct Printer {
    prayers: PrayerTimes,
    opts: Arc<Opts>,
    config: Arc<Config>,
}
impl Printer {
    #[must_use]
    pub const fn new(prayers: PrayerTimes, opts: Arc<Opts>, config: Arc<Config>) -> Self {
        Self {
            prayers,
            opts,
            config,
        }
    }
        pub fn all(&self) -> Result<(), crate::Error> {
        let prayers = self.prayers;
        let fmt_output = |name: &str, time: civil::DateTime| -> Result<String, crate::Error> {
            Ok(format!("{}: {}", name, self.format_time(time)))
        };
        Self::print(&fmt_output(&format!("{}", t!("fajr")), prayers.fajr)?);
        Self::print(&fmt_output(&format!("{}", t!("sherook")), prayers.sherook)?);
        Self::print(&fmt_output(&format!("{}", t!("dohr")), prayers.dohr)?);
        Self::print(&fmt_output(&format!("{}", t!("asr")), prayers.asr)?);
        Self::print(&fmt_output(&format!("{}", t!("maghreb")), prayers.maghreb)?);
        Self::print(&fmt_output(&format!("{}", t!("ishaa")), prayers.ishaa)?);
        Self::print(&fmt_output(
            &format!("{}", t!("first_third")),
            prayers.first_third_of_night,
        )?);
        Self::print(&fmt_output(
            &format!("{}", t!("midnight")),
            prayers.midnight,
        )?);
        Self::print(&fmt_output(
            &format!("{}", t!("last_third")),
            prayers.last_third_of_night,
        )?);
        Ok(())
    }
        pub fn current(&self) -> Result<(), crate::Error> {
        let prayers = self.prayers;
        let prayer = prayers.current();
        let (hour, minute) = prayers.time_remaining();
        let remaining_fmt = {
            if hour == 0 {
                format!("({minute} minutes left)")
            } else {
                format!("({hour}:{minute} hours left)")
            }
        };
                let mut prayer_fmt = format!("{} {}", prayer.name(), remaining_fmt);
        let state = {
            if hour == 0 && minute < 30 {
                "Critical"
            } else {
                "Info"
            }
        };
                if self.opts.json {
            prayer_fmt = format!(
                r#"{{"icon": "{}", "state": "{}", "text": "{} {}"}}"#,
                "bilal", state, "\u{23fa} ", prayer_fmt
            );
        }
                if state == "Critical" {
            prayer_fmt = format!(
                "{}",
                prayer_fmt.if_supports_color(Stdout, |text| text.red())
            );
        }
        Self::print(&prayer_fmt);
        Ok(())
    }
        pub fn next(&self) -> Result<(), crate::Error> {
        let prayers = self.prayers;
        let prayer = prayers.next();
        let time = prayers.time(prayer);
        let time = self.format_time(time);
                let mut prayer_fmt = format!("{} ({})", prayer.name(), time);
                let state = "Info";
        if self.opts.json {
            prayer_fmt = format!(
                r#"{{"icon": "{}", "state": "{}", "text": "{} {}"}}"#,
                "bilal", state, "\u{25b6}", prayer_fmt
            );
        }
        Self::print(&prayer_fmt);
        Ok(())
    }
    fn format_time(&self, time: civil::DateTime) -> String {
        match &self.config.time_format {
            TimeFormat::H24 => time.strftime("%H:%M").to_string(),
            TimeFormat::H12 => time.strftime("%I:%M %p").to_string(),
        }
    }
    fn print(prayer_fmt: &str) {
        writeln!(io::stdout(), "{prayer_fmt}").ok();
    }
}