use anyhow::{Result, anyhow};
use clap::CommandFactory;
use clap::Parser;
use std::io;

use dtox::{cli, processor};

fn main() -> Result<()> {
    let cli = cli::Cli::parse();

    if let Some(command) = cli.command {
        match command {
            cli::Command::Completion { shell } => {
                let mut cmd = cli::Cli::command();
                let name = cmd.get_name().to_string();
                clap_complete::generate(shell, &mut cmd, name, &mut io::stdout());
            }
        }
        return Ok(());
    }

    // Default action is to generate
    let args = cli.generate_args;

    // Initialize logger - respects RUST_LOG environment variable
    // If RUST_LOG is not set, use verbose flag to set level
    if std::env::var("RUST_LOG").is_ok() {
        env_logger::init();
    } else if args.verbose {
        env_logger::builder()
            .filter_level(log::LevelFilter::Info)
            .init();
    } else {
        env_logger::builder()
            .filter_level(log::LevelFilter::Warn)
            .init();
    }

    // --- Path validation ---
    if !args.input_dir.is_dir() {
        return Err(anyhow!(
            "Input directory not found or is not a directory: {}",
            args.input_dir.display()
        ));
    }
    if let Some(list_file) = &args.list_file {
        if !list_file.is_file() {
            return Err(anyhow!(
                "List file not found or is not a file: {}",
                list_file.display()
            ));
        }
    }
    if let Some(template_dir) = &args.template_dir {
        if !template_dir.is_dir() {
            return Err(anyhow!(
                "Template directory not found or is not a directory: {}",
                template_dir.display()
            ));
        }
    }

    log::info!("Starting generator...");

    // Determine template directory
    let template_dir = args
        .template_dir
        .clone()
        .unwrap_or_else(|| args.input_dir.clone());

    log::info!("Using input directory: {}", args.input_dir.display());
    log::info!("Using output directory: {}", args.output_dir.display());
    log::info!("Using template directory: {}", template_dir.display());
    if let Some(list_file) = &args.list_file {
        log::info!("Using list file: {}", list_file.display());
    }

    // Handle output directory
    if args.output_dir.exists() {
        if !args.keep {
            log::info!("Cleaning output directory: {}", args.output_dir.display());
            std::fs::remove_dir_all(&args.output_dir)?;
            std::fs::create_dir_all(&args.output_dir)?;
        } else {
            log::info!("Keeping existing output directory contents.");
        }
    } else {
        std::fs::create_dir_all(&args.output_dir)?;
        log::info!("Created output directory: {}", args.output_dir.display());
    }

    if let Err(e) = processor::run(&args) {
        log::error!("Application error: {e}");
        std::process::exit(1);
    }

    log::info!("Generation complete.");

    Ok(())
}
