#![deny(unused_crate_dependencies)]
#![allow(unused_crate_dependencies)] // Allow because the implicit self-dependency isn't used

use anyhow::Result;
use clap::Parser;
#[cfg(feature = "mcp")]
use scan_crate::{
    fetchers::CompositeFetcher, perform_inspection, run_mcp_server, InspectionParams,
};
use serde_json::json;
// use simplelog::{Config, LevelFilter, WriteLogger}; // Use tracing_subscriber instead for flexibility
use std::fs::File;
use std::io::stderr; // For stderr logger // Added for File::create
                     // use std::panic; // Comment out panic hook for now
use tracing_subscriber::EnvFilter; // For filtering tracing events based on environment variables

/// Command-line arguments
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
struct Cli {
    /// Crate specification (e.g., "serde", "serde@1.0.130")
    #[arg(long)]
    crate_spec: Option<String>,

    /// Regex query to search for within the crate source code
    #[arg(long)]
    query: Option<String>,

    /// Optional flag for case-sensitive search (defaults to false)
    #[arg(long)]
    case_sensitive: Option<bool>,

    /// Run as an MCP server instead of performing a direct inspection
    #[arg(long)]
    mcp: bool,
}

#[tokio::main] // Restore tokio main
async fn main() -> Result<()> {
    let args = Cli::parse(); // Parse args inside async main

    if args.mcp {
        // MCP Mode: Log to a file in the system temporary directory.
        let mut temp_log_path = std::env::temp_dir();
        temp_log_path.push("scan_crate_mcp.log");

        match File::create(&temp_log_path) {
            Ok(log_file) => {
                tracing_subscriber::fmt()
                    .with_env_filter(
                        EnvFilter::from_default_env().add_directive("info".parse().unwrap()),
                    )
                    .with_ansi(false) // Disable ANSI color codes
                    .with_writer(log_file) // Write to file
                    .init();
            }
            Err(e) => {
                panic!(
                    "Failed to create log file at {}: {:?}",
                    temp_log_path.display(),
                    e
                );
            }
        }
    } else {
        // CLI Mode: Log formatted events to stderr (or file if preferred)
        tracing_subscriber::fmt()
            .with_env_filter(EnvFilter::from_default_env().add_directive("info".parse()?))
            .with_writer(stderr) // Keep logging to stderr for CLI mode as well for now
            .init();
        tracing::info!(message = "Logger initialized for CLI mode (stderr).", args = ?args);
    }

    if args.mcp {
        // Run as MCP server
        #[cfg(feature = "mcp")]
        {
            tracing::info!("Starting scan_crate as MCP server...");
            tracing::debug!("[MCP Flow] src/main.rs: About to call run_mcp_server()");
            match run_mcp_server().await {
                Ok(()) => tracing::debug!(
                    "[MCP Flow] src/main.rs: run_mcp_server() completed successfully."
                ),
                Err(e) => {
                    tracing::error!("[MCP Flow] src/main.rs: run_mcp_server() failed: {:?}", e)
                }
            }
            tracing::info!("MCP server finished.");
        }
        // Add a fallback for when mcp feature is not enabled but --mcp is passed
        #[cfg(not(feature = "mcp"))]
        {
            tracing::error!(
                "Error: Program compiled without MCP feature, but --mcp flag was provided."
            );
            tracing::error!(
                "Recompile with 'cargo build --features mcp' to enable MCP server mode."
            );
            // Return an anyhow error
            return Err(anyhow::anyhow!(
                "MCP feature not enabled but --mcp flag used"
            ));
        }
    } else {
        // Perform direct inspection via CLI args
        tracing::info!("Performing direct inspection via CLI args.");
        #[cfg(feature = "mcp")]
        {
            // Use anyhow context for better error messages
            if let (Some(crate_spec_str), Some(query_str)) = (&args.crate_spec, &args.query) {
                tracing::info!(message = "Direct inspection parameters", crate_spec = %crate_spec_str, query = %query_str);

                let inspection_params = InspectionParams {
                    crate_spec: crate_spec_str.clone(),
                    query: query_str.clone(),
                    case_sensitive: args.case_sensitive.unwrap_or(false), // Provide default if None
                };

                let fetcher = CompositeFetcher::new();
                match perform_inspection(inspection_params, &fetcher).await {
                    Ok(json_value) => {
                        tracing::info!("Direct inspection successful.");
                        // Use ? directly, anyhow will convert serde_json::Error
                        let output_str = serde_json::to_string_pretty(&json_value)?;
                        println!("{output_str}"); // Print result to stdout for CLI usage
                    }
                    Err(e) => {
                        // Error is already anyhow::Error from perform_inspection
                        tracing::error!("Direct inspection failed: {}", e);
                        // Format error for JSON output
                        let error_json = json!({ "error": e.to_string() });
                        // Print JSON error to stdout for CLI usage
                        println!("{}", serde_json::to_string_pretty(&error_json)?);
                        std::process::exit(1);
                    }
                }
            } else {
                tracing::error!(
                    "Error: Both --crate-spec and --query are required for direct inspection."
                );
                std::process::exit(1);
            }
        }
        // Add a fallback for non-mcp builds trying direct inspection
        #[cfg(not(feature = "mcp"))]
        {
            tracing::error!(
                "Error: Program compiled without MCP feature, which is required for inspection."
            );
            tracing::error!("Recompile with 'cargo build --features mcp'.");
            std::process::exit(1);
        }
    }

    tracing::info!("scan_crate main finished successfully.");
    Ok(())
}
