use crate::{
    commands::{Config, Result, not_available},
    entities::{Limit, format_date, format_duration, format_invoice_no, format_revenue},
    jobber::Jobber,
    views::ApplyTableStyle,
};
use color_print::cwriteln;
use tabled::{
    Table, Tabled,
    settings::{Alignment, Width, object::Columns},
};

#[derive(Tabled)]
pub(crate) struct InvoiceView {
    #[tabled(rename = "Inv.No.")]
    pub(crate) no: String,
    #[tabled(rename = "Date")]
    pub(crate) date: String,
    #[tabled(rename = "Client")]
    pub(crate) client: String,
    #[tabled(rename = "Subject")]
    pub(crate) subject: String,
    #[tabled(rename = "Work")]
    pub(crate) worked: String,
    #[tabled(rename = "Price")]
    pub(crate) revenue: String,
    #[tabled(rename = "Tax")]
    pub(crate) tax: String,
    #[tabled(rename = "Price (tax inclusive)")]
    pub(crate) revenue_taxed: String,
}

impl InvoiceView {
    pub(crate) fn new(invoice_no: usize, database: &impl Jobber, ansi: bool) -> Result<Self> {
        let invoice = database.get_invoice(invoice_no)?;
        Ok(Self {
            no: format_invoice_no(invoice_no, invoice.deleted, ansi)?,
            date: format_date(invoice.date),
            client: database.get_full_client_name(&invoice.client)?,
            subject: invoice.subject.clone().unwrap_or(not_available(ansi)),
            worked: format_duration(invoice.worked(), Limit::None, ansi),
            revenue: format_revenue(invoice.revenue()?, ansi),
            tax: format_revenue(invoice.tax()?, ansi),
            revenue_taxed: format_revenue(invoice.revenue_taxed()?, ansi),
        })
    }
}

pub(crate) fn create_invoice_table(rows: impl IntoIterator<Item = InvoiceView>, config: &Config) -> Table {
    let mut table = Table::new(rows);
    table.modify(Columns::first(), Alignment::right());
    table.modify(Columns::one(4), Width::wrap(40));
    table.modify(Columns::one(5), Alignment::right());
    table.modify(Columns::one(6), Alignment::right());
    table.modify(Columns::one(7), Alignment::right());
    table.modify(Columns::one(8), Alignment::right());
    table.style(&config.table_style);
    table
}

impl std::fmt::Display for InvoiceView {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        cwriteln!(f, "   Invoice No: <s>{}</>", self.no,)?;
        cwriteln!(f, "         Date: <s>{}</>", self.date)?;
        cwriteln!(f, "       Client: <s>{}</>", self.client)?;
        if !self.subject.is_empty() {
            cwriteln!(f, "      Subject: <i>{}</>", &self.subject)?;
        }
        if !self.worked.is_empty() {
            cwriteln!(f, "         Work: {}", self.worked)?;
            cwriteln!(f, "      Revenue: {}", self.revenue)?;
        }
        Ok(())
    }
}
