//! Proto-gen: Protobuf code generator for <<project_name>>
//!
//! This tool generates Rust code from .proto files with serde support.
//!
//! Usage:
//! ```bash
//! cargo run -p proto-gen -- all
//! cargo run -p proto-gen -- rust
//! # or
//! make proto
//! ```

use anyhow::{Context, Result};
use clap::{Parser, Subcommand};
use std::path::PathBuf;

mod generator;

use generator::RustGenerator;

/// Proto-gen CLI - Generate code from protobuf definitions
#[derive(Parser, Debug)]
#[command(name = "proto-gen")]
#[command(about = "Generate Rust code from protobuf definitions")]
#[command(color = clap::ColorChoice::Auto)]
struct Cli {
    #[command(subcommand)]
    command: Commands,

    /// Proto files directory (relative to project root)
    #[arg(short, long, default_value = "protos")]
    proto_dir: PathBuf,

    /// Output directory for generated code (relative to project root)
    #[arg(short, long)]
    output: Option<PathBuf>,
}

#[derive(Subcommand, Debug)]
enum Commands {
    /// Generate all code (Rust)
    All,
    /// Generate Rust protobuf code
    Rust,
}

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

    // Get project root directory
    let project_root = get_project_root()?;
    let proto_dir = project_root.join(&cli.proto_dir);
    let output_dir = cli
        .output
        .map(|o| project_root.join(o))
        .unwrap_or_else(|| project_root.join("src").join("protos"));

    match cli.command {
        Commands::All | Commands::Rust => {
            println!("Generating Rust protobuf code...");
            generate_rust(&proto_dir, &output_dir)?;
            println!("Rust protobuf code generated successfully!");
        }
    }

    Ok(())
}

/// Get the project root directory
fn get_project_root() -> Result<PathBuf> {
    let current_dir = std::env::current_dir().context("Failed to get current directory")?;

    // Navigate from tools/proto-gen to project root
    if current_dir.ends_with("proto-gen") {
        Ok(current_dir
            .parent()
            .and_then(|p| p.parent())
            .map(|p| p.to_path_buf())
            .unwrap_or(current_dir))
    } else if current_dir.ends_with("tools") {
        Ok(current_dir
            .parent()
            .map(|p| p.to_path_buf())
            .unwrap_or(current_dir))
    } else {
        Ok(current_dir)
    }
}

/// Generate Rust protobuf code
fn generate_rust(proto_dir: &PathBuf, output_dir: &PathBuf) -> Result<()> {
    let generator = RustGenerator::new(proto_dir.clone(), output_dir.clone());
    generator.generate()
}
