//! Root clap parser and dispatch entry point.

use clap::Parser;
use miette::Result;
use std::process::ExitCode;
use tracing_subscriber::{EnvFilter, fmt};

use crate::commands::Command;
use crate::common::diagnostics::install_miette_handler;

/// Top-level `atproto-devtool` CLI.
#[derive(Debug, Parser)]
#[command(
    name = "atproto-devtool",
    version,
    about = "Diagnostics and conformance tooling for atproto services.",
    long_about = None,
)]
pub struct Cli {
    /// Enable verbose (DEBUG-level) logging to stderr.
    #[arg(long, global = true)]
    verbose: bool,

    /// Disable ANSI color in rendered diagnostics.
    #[arg(long, global = true)]
    no_color: bool,

    #[command(subcommand)]
    command: Command,
}

/// Parse `std::env::args()`, install global handlers, and dispatch.
///
/// Returns `Result<ExitCode, miette::Report>` to propagate exit codes through
/// the dispatch chain. The main handler renders errors with exit code 1.
pub async fn run() -> Result<ExitCode> {
    let cli = Cli::parse();

    install_miette_handler(cli.no_color)?;
    install_tracing(cli.verbose);

    cli.command.run(cli.no_color).await
}

fn install_tracing(verbose: bool) {
    let default_filter = if verbose { "debug" } else { "warn" };
    let filter =
        EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new(default_filter));

    let _ = fmt()
        .with_env_filter(filter)
        .with_writer(std::io::stderr)
        .try_init();
}
