//! CLI entry point for typedialog-prov-gen.

use clap::Parser;
use std::path::PathBuf;

#[derive(Parser, Debug)]
#[command(name = "typedialog-prov-gen")]
#[command(about = "Generate provisioning structures for typedialog projects", long_about = None)]
struct Cli {
    /// Subcommand to execute
    #[command(subcommand)]
    command: Commands,

    /// Configuration file (TOML)
    ///
    /// If provided, uses this file exclusively.
    /// If not provided, searches: ~/.config/typedialog/prov-gen/{TYPEDIALOG_ENV}.toml → ~/.config/typedialog/prov-gen/config.toml → defaults
    #[arg(global = true, short = 'c', long, value_name = "FILE")]
    config: Option<PathBuf>,

    /// Enable verbose logging
    #[arg(short, long, global = true)]
    verbose: bool,
}

#[derive(Parser, Debug)]
enum Commands {
    /// Generate provisioning structure from project specification
    Generate {
        /// Input mode: cargo | config | wizard | nickel
        #[arg(short, long)]
        mode: String,

        /// Input file path (for modes that require files)
        #[arg(short, long)]
        input: Option<PathBuf>,

        /// Output directory for generated files
        #[arg(short, long, default_value = "./provisioning")]
        output: PathBuf,

        /// Project name override
        #[arg(short, long)]
        project: Option<String>,

        /// Overwrite existing files
        #[arg(short, long)]
        force: bool,

        /// Dry run (show what would be generated)
        #[arg(long)]
        dry_run: bool,
    },

    /// Validate a provisioning structure
    Validate {
        /// Path to provisioning directory
        #[arg(value_name = "DIR")]
        path: PathBuf,
    },

    /// List available templates
    Templates {
        /// Output format: json, yaml, text, toml
        #[arg(short, long, value_name = "FORMAT", default_value = "text")]
        format: String,
    },

    /// Show help for a specific input mode
    ModeHelp {
        /// Mode name (cargo, config, wizard, nickel)
        #[arg(value_name = "MODE")]
        mode: Option<String>,
    },
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let cli = Cli::parse();

    // Initialize logging
    let level = if cli.verbose {
        tracing::metadata::LevelFilter::DEBUG
    } else {
        tracing::metadata::LevelFilter::INFO
    };
    tracing_subscriber::fmt().with_max_level(level).init();

    match cli.command {
        Commands::Generate {
            mode,
            input,
            output,
            project,
            force,
            dry_run,
        } => {
            use typedialog_prov_gen::cli::GenerateCommand;
            use typedialog_prov_gen::config::Config;

            // Load configuration
            let _config = match Config::load(cli.config.as_deref()) {
                Ok(cfg) => cfg,
                Err(e) => {
                    eprintln!("Failed to load configuration: {}", e);
                    std::process::exit(1);
                }
            };

            if !force
                && output.exists()
                && std::fs::read_dir(&output)
                    .ok()
                    .is_some_and(|mut dir| dir.next().is_some())
            {
                eprintln!("Output directory already exists. Use --force to overwrite");
                std::process::exit(1);
            }

            if let Err(e) = GenerateCommand::execute(&mode, input, output, project, dry_run).await {
                eprintln!("Generation failed: {}", e);
                std::process::exit(1);
            }
        }

        Commands::Validate { path: _ } => {
            // TODO: Implement validation command
            eprintln!("Validation command not yet implemented");
            std::process::exit(1);
        }

        Commands::Templates { format } => {
            use typedialog_prov_gen::config::Config;
            use typedialog_prov_gen::template::TemplateLoader;

            match Config::load(cli.config.as_deref()) {
                Ok(config) => match TemplateLoader::new(&config) {
                    Ok(loader) => match loader.list_templates() {
                        Ok(categories) => match format.as_str() {
                            "json" => {
                                if let Ok(json) = serde_json::to_string_pretty(&categories) {
                                    println!("{}", json);
                                } else {
                                    eprintln!("Failed to serialize templates to JSON");
                                    std::process::exit(1);
                                }
                            }
                            "yaml" => {
                                if let Ok(yaml) = serde_yaml::to_string(&categories) {
                                    println!("{}", yaml);
                                } else {
                                    eprintln!("Failed to serialize templates to YAML");
                                    std::process::exit(1);
                                }
                            }
                            "toml" => {
                                use serde::Serialize;
                                #[derive(Serialize)]
                                struct TemplatesWrapper {
                                    categories:
                                        Vec<typedialog_prov_gen::template::TemplateCategory>,
                                }
                                let wrapped = TemplatesWrapper { categories };
                                if let Ok(toml) = toml::to_string_pretty(&wrapped) {
                                    println!("{}", toml);
                                } else {
                                    eprintln!("Failed to serialize templates to TOML");
                                    std::process::exit(1);
                                }
                            }
                            "text" => {
                                println!("From: {}\n", loader.templates_dir().display());
                                println!("📋 Available Template Categories:\n");
                                for category in categories {
                                    println!(
                                        "{}  {}",
                                        category.name.to_uppercase(),
                                        category.description
                                    );
                                    for template in &category.templates {
                                        println!("  • {}", template);
                                    }
                                    println!();
                                }
                            }
                            _ => {
                                eprintln!(
                                    "Unknown format: {}. Supported: json, yaml, text, toml",
                                    format
                                );
                                std::process::exit(1);
                            }
                        },
                        Err(e) => {
                            eprintln!("Failed to list templates: {}", e);
                            std::process::exit(1);
                        }
                    },
                    Err(e) => {
                        eprintln!("Failed to initialize template loader: {}", e);
                        std::process::exit(1);
                    }
                },
                Err(e) => {
                    eprintln!("Failed to load configuration: {}", e);
                    std::process::exit(1);
                }
            }
        }

        Commands::ModeHelp { mode } => match mode.as_deref() {
            Some("cargo") => {
                println!("Mode: cargo\n\nAnalyze Cargo.toml to infer project configuration")
            }
            Some("config") => println!("Mode: config\n\nLoad explicit project-spec.toml"),
            Some("wizard") => println!("Mode: wizard\n\nInteractive AI-powered wizard"),
            Some("nickel") => println!("Mode: nickel\n\nAugment existing Nickel schema"),
            _ => {
                println!("Available modes:");
                println!("  cargo   - Analyze Cargo.toml (automatic feature detection)");
                println!("  config  - Load explicit project-spec.toml");
                println!("  wizard  - Interactive AI-powered wizard");
                println!("  nickel  - Augment existing Nickel schema");
            }
        },
    }

    Ok(())
}
