use std::{fs::create_dir_all, path::PathBuf, process::exit};

use clap::{arg, Parser, Subcommand};
use config::Config;
use site::Site;

/// This module contains additional filters loaded in the
/// website's [`tera::Tera`] instance
pub mod filters;

pub mod config;
pub mod page;
pub mod site;
pub mod theme;

/// Command line interface for the rubedo executable
///
/// It can be run without arguments to invoke the "generate" functionality
/// or with a [`SubCommand`]
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
struct Cli {
    /// Run as if started from CWD, defaults to `.`
    #[arg(short = 'C', default_value_t = String::from("."))]
    pub cwd: String,
    #[command(subcommand)]
    command: Option<SubCommand>,
}

/// Command line sub-commands supported by the rubedo executable
#[derive(Subcommand, Debug)]
enum SubCommand {
    /// Initialize a new website, generating the required configuration
    /// and setting up some of the directories
    Init(InitArgs),
}

/// Command line arguments for [`SubCommand::Init`]
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
struct InitArgs {
    /// Title of the website
    #[arg(short = 't', long)]
    pub title: Option<String>,

    /// Language code for the website
    #[arg(short, long)]
    pub language: Option<String>,

    /// Run as if started from CWD
    #[arg(short = 'C', default_value_t = String::from("."))]
    pub cwd: String,
}

fn main() {
    let cli = Cli::parse();

    match &cli.command {
        Some(SubCommand::Init(init_args)) => {
            let path = PathBuf::from(&init_args.cwd);
            if !path.is_dir() {
                eprintln!("Error: path '{}' is not a directory", init_args.cwd);
                exit(1);
            }
            let config_path = path.join("config.toml");
            if config_path.is_file() {
                eprintln!("Error: path '{}' appears to already contain a config.toml file. Did you already initialize the website?", init_args.cwd);
                exit(1);
            }
            create_dir_all(path.join("content")).expect("Could not create 'content' directory");
            let mut config = Config::default();
            if let Some(title) = init_args.title.as_ref() {
                config.title = title.clone();
            }
            if let Some(lang) = init_args.language.as_ref() {
                config.language = lang.clone();
            }
            std::fs::write(config_path, config.toml()).expect("Failed to write config.toml");
        }
        None => {
            let cwd = PathBuf::from(cli.cwd);

            match Site::new(cwd) {
                Ok(site) => {
                    if let Err(e) = site.generate() {
                        eprintln!("Error generating website: {e:#?}");
                        exit(1);
                    };
                }
                Err(e) => {
                    eprintln!("Error loading website: {e:#?}");
                    exit(1);
                }
            }
        }
    }
}
