use clap::Parser;
use color_print::ceprintln;
use commands::*;

mod commands;
mod database;
mod entities;
mod jobber;
mod templates;
mod views;

fn main() {
    let cli = Cli::parse();
    let result = if let Some(command) = &cli.command {
        command.run(&cli)
    } else {
        Info::default().run(&cli)
    };
    if let Err(err) = result {
        ceprintln!("<r!>{err}</>");
        if !cli.no_tips {
            tip(err);
        }
    }
}

fn tip(err: Error) {
    ceprintln!();
    match err {
        Error::CannotOpenDatabase(..) => {
            ceprintln!("Use <s>jobber init</> to create a new database.")
        }
        Error::CannotReadDatabase(path_buf, _) => {
            ceprintln!("Seems your database file <s>{path_buf:?}</> is corrupted :/")
        }
        Error::CannotWriteDatabase(..) => {
            ceprintln!("Try using <s>jobber undo</> to restore the last backup.")
        }
        Error::Database(error) => match error {
            database::Error::ClientExists(_) => {
                ceprintln!("Use an alternative identifier for the new client.")
            }
            database::Error::WorkerExists(_) => {
                ceprintln!("Use an alternative identifier for the new worker.")
            }
            database::Error::UnknownWorker(worker) => {
                ceprintln!("Use <s>jobber list workers</> to check for the correct identifier.");
                ceprintln!("Check if <s>{worker}</> is spelled correctly.")
            }
            database::Error::UnknownClient(client) => {
                ceprintln!("Use <s>jobber list client</> to check for the correct identifier.");
                ceprintln!("Check if <s>{client}</> is spelled correctly.")
            }
            database::Error::JobNotFound(pos) => {
                ceprintln!("Use <s>jobber list jobs</> to list all jobs.");
                ceprintln!("Check if <s>{pos}</> is the correct position.")
            }
            database::Error::AlreadyWorking { .. } => {
                ceprintln!("Use <s>jobber end</> to finish the current work.")
            }
            database::Error::DescriptionExists(_) => {
                ceprintln!("Use <s>-a</> (append) or <s>-r</> (replace) the existing description.");
            }
            database::Error::DescriptionMissing => {
                ceprintln!(
                    "Add a description as argument (use \" to quote text which includes spaces)."
                );
            }
            database::Error::NotWorking => {
                ceprintln!("Use <s>jobber start</> to begin work.");
            }
            database::Error::EndsBeforeStart(_, _) => {
                ceprintln!("Fix the start and end time arguments.");
            }
            database::Error::WorkerNotFound(_) => {
                ceprintln!("Use <s>jobber list workers</> to get a list of all workers.")
            }
            database::Error::ClientNotFound(_) => {
                ceprintln!("Use <s>jobber list clients</> to get a list of all clients.")
            }
            database::Error::TagNotFound(_) => {
                ceprintln!("Use <s>jobber list tags</> to get a list of all tags.")
            }
            database::Error::InvoiceNotFound(_) => {
                ceprintln!("Use <s>jobber list invoices</> to get a list of all invoices.")
            }
            database::Error::Entity(_) => (),
            database::Error::NoCompany => {
                ceprintln!("Use <s>jobber create company</> to add your company data.")
            }
            database::Error::WorkNotFound(job, _) => {
                ceprintln!("Use <s>jobber list job {job}</> to get a list of the work.")
            }
            database::Error::Inquire(_) => (),
            database::Error::TagExists(_) => (),
        },
        Error::Io(..) => (),
        Error::Confy(..) => (),
        Error::Json(..) => (),
        Error::Entities(error) => match error {
            entities::Error::InvalidWorkingInterval(_) => todo!(),
            entities::Error::CouldNotParseRate(why, _) => {
                ceprintln!("{why}: Fix rate format (e.g. 50usd/hour, 1000eur/month, 10eur/15min)")
            }
            entities::Error::CouldNotParseBillingPeriod(_) => todo!(),
            entities::Error::UnknownInterval(_) => todo!(),
            entities::Error::Money(_) => todo!(),
            entities::Error::NoRate => todo!(),
            entities::Error::CouldNotParseDateTime(_) => todo!(),
            entities::Error::DateTimeParse(_) => todo!(),
            entities::Error::InvalidDateValues(_, _, _) => todo!(),
            entities::Error::JobMissingScheme(job_id) => {
                ceprintln!("Use <s>jobber edit job {job_id} to enter a valid scheme")
            }
        },
        Error::ParseIntError(..) => (),
        Error::CannotConvertDateTime(_) => {
            ceprintln!("Check the available input formats:");
            todo!("list formats")
        }
        Error::NoCurrentJob => {
            ceprintln!("Use <s>jobber select</> to select a job.");
            ceprintln!("Use <s>jobber create job</> to create a new job.");
        }
        Error::InvalidRange(_, _) => {
            ceprintln!("Keep start and end in the chronological order. ")
        }
        Error::Typst(err) => ceprintln!("Typst error: {err}"),
        Error::TypstPDF(_) => todo!(),
        Error::CurrentJobDeleted(_) => {
            ceprintln!("Use <s>jobber select</> to select a valid job.")
        }
        Error::NoJobsFoundInRange(_) => (),
        Error::InvalidRangeEx(_) => (),
        Error::Inquire(_) => (),
    };
}
