use std::{fs::{self, File}, process::ExitCode};
use tera::Tera;
use clap::Parser;
use inline_colorization::*;
use serde::{Serialize, Deserialize};

#[derive(Parser)]
struct Args {
    #[arg(short, long)]
    templates_path: String,
    #[arg(short, long)]
    context_path: String,
    #[arg(short, long)]
    output_dir: String,
}

#[derive(Serialize, Deserialize)]
struct Person {
    name: String,
    role: String,
    mail: String,
    phone: String,
}

#[derive(thiserror::Error, Debug)]
enum Error {
    // #[error("{style_bold}{color_red}Unknown Error: {style_reset}{color_reset}\n")]
    // UnknownError,
    #[error("{style_bold}{color_red}io Error: {style_reset}{color_reset}\n{0}")]
    TeraError(#[from] tera::Error),
    #[error("{style_bold}{color_red}io Error: {style_reset}{color_reset}\n{0}")]
    Io(#[from] std::io::Error),
    #[error("{style_bold}{color_red}io Error: {style_reset}{color_reset}\n{0}")]
    Ron(#[from] ron::error::SpannedError),
}

fn run(args: Args) -> Result<(), Error> {
    let template = Tera::new(&args.templates_path)?;

    let person_conts = fs::read_to_string(&args.context_path)?;
    let person: Person = ron::from_str(&person_conts)?;
    let context = tera::Context::from_serialize(&person)?;

    for tn in template.get_template_names() {
        // Think of something better for file naming here
        let f = File::create_new(format!("{}/{}_{}", &args.output_dir, &person.name.split(' ').next().unwrap(), tn))?;
        template.render_to(tn, &context, f)?;
    }
    
    Ok(())
}

fn main() -> ExitCode {
    let args = Args::parse();
    match run(args) {
        Ok(_) => ExitCode::SUCCESS,
        Err(e) => {
            eprintln!("{e}");
            ExitCode::FAILURE
        }
    }
}
