use crate::{
    commands::{Config, Result},
    entities::{Limit, format_duration, format_worker_id},
    jobber::{JobberGet, JobberIter, JobberWork},
    views::ApplyTableStyle,
};
use tabled::{
    Table, Tabled,
    settings::{Alignment, object::Columns},
};

#[derive(Tabled)]
pub(crate) struct WorkerView {
    #[tabled(skip)]
    pub(crate) order: String,
    #[tabled(rename = "ID")]
    pub(crate) id: String,
    #[tabled(rename = "Full Name")]
    pub(crate) full_name: String,
    #[tabled(rename = "Work")]
    pub(crate) work: String,
}

impl WorkerView {
    pub(crate) fn new(
        worker_id: &String,
        config: &Config,
        database: &(impl JobberGet + JobberWork + JobberGet + JobberIter),
        ansi: bool,
    ) -> Result<Self> {
        let duration = database.duration_by_worker(worker_id);
        let worker = database.get_worker(worker_id)?;
        Ok(Self {
            order: worker_id.clone(),
            id: format_worker_id(worker_id, database, config, ansi)?,
            full_name: worker.full_name.clone(),
            work: format_duration(duration, Limit::None, ansi),
        })
    }
}

impl std::fmt::Display for WorkerView {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        writeln!(f, " Worker ID: {}", self.id)?;
        writeln!(f, " Full Name: {}", self.full_name)?;
        write!(f, "    Worked: {}", self.work)
    }
}

pub(crate) fn create_worker_table(
    rows: impl IntoIterator<Item = WorkerView>,
    config: &Config,
) -> Table {
    let mut table = Table::new(rows);
    table.modify(Columns::first(), Alignment::right());
    table.modify(Columns::one(2), Alignment::right());
    table.style(&config.table_style);
    table
}
