use color_print::cformat;
use tabled::{
    Table, Tabled,
    settings::{Alignment, Span, object::Rows},
};

use crate::{
    commands::Config,
    entities::{DateTime, Limit, format_hours},
};

#[derive(Tabled, Default)]
pub(crate) struct CalendarView {
    #[tabled(rename = "  Day")]
    pub(crate) day: String,
    #[tabled(rename = "  Sun")]
    pub(crate) sunday: String,
    #[tabled(rename = "  Mon")]
    pub(crate) monday: String,
    #[tabled(rename = "  Tue")]
    pub(crate) tuesday: String,
    #[tabled(rename = "  Wed")]
    pub(crate) wednesday: String,
    #[tabled(rename = "  Thu")]
    pub(crate) thursday: String,
    #[tabled(rename = "  Fri")]
    pub(crate) friday: String,
    #[tabled(rename = "  Sat")]
    pub(crate) saturday: String,
    #[tabled(rename = "  Week")]
    pub(crate) week: String,
}

impl CalendarView {
    pub(crate) fn new(day: i32, days: [Option<f32>; 7], week: f32, ansi: bool) -> Self {
        Self {
            day: if day > 0 {
                day.to_string()
            } else {
                String::new()
            },
            sunday: days[0]
                .map(|d| format_hours(d, Limit::Day, ansi))
                .unwrap_or_default(),
            monday: days[1]
                .map(|d| format_hours(d, Limit::Day, ansi))
                .unwrap_or_default(),
            tuesday: days[2]
                .map(|d| format_hours(d, Limit::Day, ansi))
                .unwrap_or_default(),
            wednesday: days[3]
                .map(|d| format_hours(d, Limit::Day, ansi))
                .unwrap_or_default(),
            thursday: days[4]
                .map(|d| format_hours(d, Limit::Day, ansi))
                .unwrap_or_default(),
            friday: days[5]
                .map(|d| format_hours(d, Limit::Day, ansi))
                .unwrap_or_default(),
            saturday: days[6]
                .map(|d| format_hours(d, Limit::Day, ansi))
                .unwrap_or_default(),
            week: format_hours(week, Limit::Week, ansi),
        }
    }

    pub(crate) fn new_sum(month: DateTime, sum: f32, ansi: bool) -> Self {
        Self {
            day: cformat!(
                "{}: <s>{}</> hrs",
                month.format("%b %Y"),
                format_hours(sum, Limit::Month, ansi)
            ),
            ..Default::default()
        }
    }
}

pub(crate) fn create_calendar_table(
    rows: impl IntoIterator<Item = CalendarView>,
    config: &Config,
) -> Table {
    let mut table = Table::new(rows);
    table
        .with(config.calendar_theme())
        .modify(Rows::last(), Span::column(9))
        .with(Alignment::right())
        .modify(Rows::first(), Alignment::center())
        .modify(Rows::last(), Alignment::right());

    table
}
