use anyhow::Result;
use clap::{Parser, Subcommand};
use colored::*;
use std::path::PathBuf;
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};

mod analyzers;
mod config;
mod parsers;
mod reporters;
mod rules;
mod scanner;
mod types;

use crate::config::AppConfig;
use crate::reporters::{ConsoleReporter, JsonReporter, Reporter};
use crate::scanner::{RemoteScanner, Scanner};

const VERSION: &str = "1.7.0";
const API_BASE_URL: &str = "https://kybercheck.com";

/// Print the cool ASCII art banner
fn print_banner() {
    let banner = r#"
    ██╗  ██╗██╗   ██╗██████╗ ███████╗██████╗  ██████╗██╗  ██╗███████╗ ██████╗██╗  ██╗
    ██║ ██╔╝╚██╗ ██╔╝██╔══██╗██╔════╝██╔══██╗██╔════╝██║  ██║██╔════╝██╔════╝██║ ██╔╝
    █████╔╝  ╚████╔╝ ██████╔╝█████╗  ██████╔╝██║     ███████║█████╗  ██║     █████╔╝ 
    ██╔═██╗   ╚██╔╝  ██╔══██╗██╔══╝  ██╔══██╗██║     ██╔══██║██╔══╝  ██║     ██╔═██╗ 
    ██║  ██╗   ██║   ██████╔╝███████╗██║  ██║╚██████╗██║  ██║███████╗╚██████╗██║  ██╗
    ╚═╝  ╚═╝   ╚═╝   ╚═════╝ ╚══════╝╚═╝  ╚═╝ ╚═════╝╚═╝  ╚═╝╚══════╝ ╚═════╝╚═╝  ╚═╝"#;
    
    println!("{}", banner.cyan());
    println!("{}", "    ⚛️  Quantum Vulnerability Scanner".white().bold());
    println!("    {}{}", "    v".dimmed(), VERSION.dimmed());
    println!();
}

/// Print a compact banner for commands
fn print_compact_banner(subtitle: &str) {
    println!(
        "{}  {}",
        "⚛ KyberCheck".cyan().bold(),
        subtitle.white()
    );
    println!("{}", "─".repeat(50).dimmed());
}

/// Format a number with thousand separators (e.g., 1234567 -> "1,234,567")
fn format_number(n: usize) -> String {
    let s = n.to_string();
    let mut result = String::new();
    for (i, c) in s.chars().rev().enumerate() {
        if i > 0 && i % 3 == 0 {
            result.push(',');
        }
        result.push(c);
    }
    result.chars().rev().collect()
}

/// Validate an API key with the KyberCheck server
/// Uses the /api/v1/auth/validate endpoint with X-API-Key header
async fn validate_api_key(api_key: &str) -> Result<bool> {
    let client = reqwest::Client::new();
    let base_url = std::env::var("KYBERCHECK_API_URL").unwrap_or_else(|_| API_BASE_URL.to_string());
    
    // Ensure API key is trimmed to avoid whitespace issues
    let trimmed_key = api_key.trim();
    
    // Validate key format before making request
    if !trimmed_key.starts_with("kc_") {
        return Err(anyhow::anyhow!("API key must start with 'kc_' prefix"));
    }
    
    // Use X-API-Key header (Vercel strips Authorization header in production)
    // Use the dedicated validate endpoint
    let response = client
        .get(format!("{}/api/v1/auth/validate", base_url))
        .header("X-API-Key", trimmed_key)
        .timeout(std::time::Duration::from_secs(10))
        .send()
        .await;
    
    match response {
        Ok(resp) => {
            let status = resp.status();
            let body_text = resp.text().await.unwrap_or_else(|_| "{}".to_string());
            
            // Try to parse as JSON
            let json: serde_json::Value = serde_json::from_str(&body_text).unwrap_or_default();
            
            match status.as_u16() {
                200 => {
                    // Check the 'valid' field from the response
                    if let Some(valid) = json.get("valid").and_then(|v| v.as_bool()) {
                        if valid {
                            Ok(true)
                        } else {
                            let error_msg = json.get("error")
                                .and_then(|e| e.as_str())
                                .unwrap_or("API key validation failed");
                            Err(anyhow::anyhow!("{}", error_msg))
                        }
                    } else {
                        // If no 'valid' field, assume success if status is 200
                        Ok(true)
                    }
                }
                401 => {
                    // Invalid, expired, or revoked key
                    let error_msg = json.get("error")
                        .and_then(|e| e.as_str())
                        .unwrap_or("Invalid or expired API key");
                    Err(anyhow::anyhow!("{}", error_msg))
                }
                429 => {
                    // Rate limited
                    Err(anyhow::anyhow!("Rate limit exceeded. Please wait and try again."))
                }
                404 => {
                    // Endpoint not found
                    Err(anyhow::anyhow!("API endpoint not found. Please update KyberCheck CLI to the latest version."))
                }
                _ => {
                    let error_msg = json.get("error")
                        .and_then(|e| e.as_str())
                        .unwrap_or("Unknown error");
                    Err(anyhow::anyhow!("API key validation failed ({}): {}", status, error_msg))
                }
            }
        }
        Err(e) => {
            if e.is_timeout() {
                Err(anyhow::anyhow!("Connection timed out while validating API key. Check your internet connection."))
            } else if e.is_connect() {
                Err(anyhow::anyhow!("Could not connect to KyberCheck servers. Check your internet connection."))
            } else {
                Err(anyhow::anyhow!("Failed to validate API key: {}", e))
            }
        }
    }
}

/// Print an error message with helpful guidance
fn print_error(title: &str, message: &str, help: Option<&str>, link: Option<&str>) {
    eprintln!();
    eprintln!("{} {}", "✖ Error:".red().bold(), title.red());
    eprintln!("  {}", message);
    if let Some(help_text) = help {
        eprintln!();
        eprintln!("  {} {}", "💡 Tip:".yellow(), help_text);
    }
    if let Some(url) = link {
        eprintln!("  {} {}", "🔗 Link:".blue(), url.underline());
    }
    eprintln!();
}

#[derive(Parser)]
#[command(name = "kybercheck")]
#[command(author = "KyberCheck Team")]
#[command(version = VERSION)]
#[command(about = "Scan codebases for quantum-vulnerable cryptography", long_about = None)]
struct Cli {
    #[command(subcommand)]
    command: Commands,

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

    /// Output format (console, json)
    #[arg(short, long, global = true, default_value = "console")]
    format: String,
}

#[derive(Subcommand)]
enum Commands {
    /// Scan a directory or file for quantum-vulnerable cryptography
    Scan {
        /// Path to scan (file or directory)
        #[arg(default_value = ".")]
        path: PathBuf,

        /// API key for authentication (required)
        #[arg(long, env = "KYBERCHECK_API_KEY")]
        api_key: Option<String>,

        /// Output file path (optional, defaults to stdout)
        #[arg(short, long)]
        output: Option<PathBuf>,

        /// Include transitive dependency analysis
        #[arg(long, default_value = "true")]
        dependencies: bool,

        /// Analyze database schema impacts
        #[arg(long, default_value = "true")]
        db_impact: bool,

        /// Fail on any vulnerability found
        #[arg(long)]
        fail_on_vuln: bool,

        /// Minimum severity to report (low, medium, high, critical)
        #[arg(long, default_value = "low")]
        min_severity: String,

        /// Exclude patterns (glob)
        #[arg(short, long)]
        exclude: Vec<String>,

        /// Only scan specific languages (comma-separated: rust,python,javascript,go,java,c,cpp,csharp,php,ruby,kotlin,swift,scala,shell,perl,lua,dart,groovy,objectivec,typescript)
        #[arg(short, long, value_delimiter = ',')]
        languages: Option<Vec<String>>,

        /// Don't submit results to KyberCheck dashboard
        #[arg(long)]
        no_submit: bool,

        /// Existing scan ID to update (for CI/CD integration)
        #[arg(long, env = "KYBERCHECK_SCAN_ID")]
        scan_id: Option<String>,

        /// API endpoint URL (defaults to https://kybercheck.com)
        #[arg(long, env = "KYBERCHECK_API_URL")]
        api_url: Option<String>,
    },

    /// Submit scan results to KyberCheck API
    Submit {
        /// Path to scan results JSON file
        results: PathBuf,

        /// API key for authentication
        #[arg(long, env = "KYBERCHECK_API_KEY")]
        api_key: Option<String>,

        /// API endpoint URL
        #[arg(long, env = "KYBERCHECK_API_URL", default_value = "https://kybercheck.com")]
        api_url: String,

        /// Repository identifier
        #[arg(long, env = "KYBERCHECK_REPO_ID")]
        repo_id: Option<String>,
    },

    /// Initialize configuration file
    Init {
        /// Force overwrite existing configuration
        #[arg(short, long)]
        force: bool,
    },

    /// Scan a remote Git repository (clones to temp directory)
    Remote {
        /// Git repository URL or GitHub shorthand (e.g., owner/repo)
        url: String,

        /// API key for authentication (required)
        #[arg(long, env = "KYBERCHECK_API_KEY")]
        api_key: Option<String>,

        /// Branch to scan (default: default branch)
        #[arg(short, long)]
        branch: Option<String>,

        /// Output file path (optional, defaults to stdout)
        #[arg(short, long)]
        output: Option<PathBuf>,

        /// Fail on any vulnerability found
        #[arg(long)]
        fail_on_vuln: bool,

        /// Minimum severity to report (low, medium, high, critical)
        #[arg(long, default_value = "low")]
        min_severity: String,

        /// Exclude patterns (glob)
        #[arg(short, long)]
        exclude: Vec<String>,

        /// Only scan specific languages (comma-separated)
        #[arg(short, long, value_delimiter = ',')]
        languages: Option<Vec<String>>,

        /// Keep cloned repository after scan (prints path)
        #[arg(long)]
        keep: bool,

    },

    /// Show supported languages and vulnerability patterns
    Info,
}

#[tokio::main]
async fn main() -> Result<()> {
    let cli = Cli::parse();

    // Initialize logging
    let log_level = if cli.verbose { "debug" } else { "warn" };
    tracing_subscriber::registry()
        .with(tracing_subscriber::EnvFilter::try_from_default_env().unwrap_or_else(|_| log_level.into()))
        .with(tracing_subscriber::fmt::layer().with_target(false))
        .init();

    match cli.command {
        Commands::Scan {
            path,
            api_key,
            output,
            dependencies,
            db_impact,
            fail_on_vuln,
            min_severity,
            exclude,
            languages,
            no_submit,
            scan_id,
            api_url,
        } => {
            run_scan(
                path,
                api_key,
                output,
                dependencies,
                db_impact,
                fail_on_vuln,
                min_severity,
                exclude,
                languages,
                &cli.format,
                no_submit,
                scan_id,
                api_url,
            )
            .await
        }
        Commands::Submit {
            results,
            api_key,
            api_url,
            repo_id,
        } => submit_results(results, api_key, api_url, repo_id).await,
        Commands::Init { force } => init_config(force),
        Commands::Remote {
            url,
            api_key,
            branch,
            output,
            fail_on_vuln,
            min_severity,
            exclude,
            languages,
            keep,
        } => {
            run_remote_scan(
                url,
                api_key,
                branch,
                output,
                fail_on_vuln,
                min_severity,
                exclude,
                languages,
                keep,
                &cli.format,
            )
            .await
        }
        Commands::Info => show_info(),
    }
}

async fn run_scan(
    path: PathBuf,
    api_key: Option<String>,
    output: Option<PathBuf>,
    analyze_dependencies: bool,
    analyze_db_impact: bool,
    fail_on_vuln: bool,
    min_severity: String,
    exclude: Vec<String>,
    languages: Option<Vec<String>>,
    format: &str,
    no_submit: bool,
    scan_id: Option<String>,
    api_url: Option<String>,
) -> Result<()> {
    // Print the banner
    print_banner();

    // Check for API key
    let api_key = match api_key {
        Some(key) if !key.is_empty() => key,
        _ => {
            print_error(
                "API key required",
                "You must provide an API key to use KyberCheck.",
                Some("Set the KYBERCHECK_API_KEY environment variable or use --api-key"),
                Some("https://kybercheck.com/dashboard/settings/api-keys"),
            );
            std::process::exit(1);
        }
    };

    // Validate the API key format first
    if !api_key.starts_with("kc_") {
        print_error(
            "Invalid API key format",
            "API keys should start with 'kc_' prefix.",
            Some("Make sure you copied the entire API key from your dashboard."),
            Some("https://kybercheck.com/dashboard/settings/api-keys"),
        );
        std::process::exit(1);
    }

    // Validate API key with server
    println!("{}", "🔐 Validating API key...".dimmed());
    match validate_api_key(&api_key).await {
        Ok(true) => {
            println!("{}", "✓ API key validated".green());
        }
        Ok(false) => {
            print_error(
                "Invalid or expired API key",
                "The API key provided is invalid, expired, or has been revoked.",
                Some("Generate a new API key from your dashboard."),
                Some("https://kybercheck.com/dashboard/settings/api-keys"),
            );
            std::process::exit(1);
        }
        Err(e) => {
            let error_msg = e.to_string();
            if error_msg.contains("Invalid API key") || error_msg.contains("expired") || error_msg.contains("revoked") {
                print_error(
                    "Invalid or expired API key",
                    &error_msg,
                    Some("Generate a new API key from your dashboard."),
                    Some("https://kybercheck.com/dashboard/settings/api-keys"),
                );
            } else if error_msg.contains("Missing authorization header") {
                print_error(
                    "API server configuration issue",
                    "The server reported 'Missing authorization header' even though one was sent.",
                    Some("This may be a temporary server issue. Please try again later."),
                    Some("https://kybercheck.com/docs/troubleshooting"),
                );
            } else {
                print_error(
                    "Could not validate API key",
                    &error_msg,
                    Some("Check your internet connection and try again."),
                    Some("https://kybercheck.com/docs/troubleshooting"),
                );
            }
            std::process::exit(1);
        }
    }

    println!();
    print_compact_banner("Local Scan");

    let config = AppConfig::new(analyze_dependencies, analyze_db_impact, min_severity, exclude, languages.clone())?;
    let scanner = Scanner::new(config);

    // Show language filter if specified
    if let Some(ref langs) = languages {
        println!(
            "{} {}",
            "Filtering languages:".blue(),
            langs.join(", ").cyan()
        );
    }

    println!(
        "{} {}",
        "📁 Scanning:".blue().bold(),
        path.display().to_string().white()
    );

    let results = scanner.scan(&path).await?;

    // Select reporter based on format
    let reporter: Box<dyn Reporter> = match format {
        "json" => Box::new(JsonReporter::new()),
        _ => Box::new(ConsoleReporter::new()),
    };

    // Output results
    match output {
        Some(output_path) => {
            let report = reporter.generate(&results)?;
            std::fs::write(&output_path, report)?;
            println!(
                "\n{} {}",
                "Results written to:".green().bold(),
                output_path.display()
            );
        }
        None => {
            reporter.print(&results)?;
        }
    }

    // Summary
    println!("\n{}", "=".repeat(50).dimmed());
    println!(
        "{} {} vulnerabilities found",
        "Summary:".blue().bold(),
        results.vulnerabilities.len().to_string().yellow().bold()
    );
    println!(
        "  {} files scanned ({} lines)",
        results.files_scanned.to_string().cyan(),
        format_number(results.lines_scanned).cyan()
    );

    if results.has_db_impact {
        println!(
            "  {} Database schema impacts detected",
            "⚠".yellow()
        );
    }

    if results.has_api_impact {
        println!(
            "  {} API payload impacts detected",
            "⚠".yellow()
        );
    }

    // Auto-submit results to KyberCheck dashboard (unless disabled)
    if !no_submit {
        println!("\n{}", "📤 Submitting results to KyberCheck...".dimmed());
        
        // Use provided api_url, else env var, else default constant
        let base_url = api_url.clone()
            .or_else(|| std::env::var("KYBERCHECK_API_URL").ok())
            .unwrap_or_else(|| API_BASE_URL.to_string());
        
        let mut payload = types::SubmissionPayload::from_results(&results);
        
        // If scan_id was provided (from dashboard/CI), use it to update the existing scan
        if let Some(ref existing_scan_id) = scan_id {
            if let Ok(uuid) = uuid::Uuid::parse_str(existing_scan_id) {
                println!("  {} Linking to existing scan: {}", "🔗".blue(), existing_scan_id);
                payload.scan_id = uuid;
            } else {
                println!("  {} Invalid scan ID format, using generated ID", "⚠".yellow());
            }
        }
        
        println!("  {} Submitting to: {}/api/v1/scans", "→".dimmed(), base_url);
        println!("  {} Scan ID: {}", "→".dimmed(), payload.scan_id);
        println!("  {} Files: {}, Lines: {}, Vulns: {}", "→".dimmed(), 
            payload.files_scanned, payload.lines_scanned, payload.vulnerabilities.len());
        
        let client = reqwest::Client::new();
        let response = client
            .post(format!("{}/api/v1/scans", base_url))
            .header("X-API-Key", &api_key)
            .header("Content-Type", "application/json")
            .json(&payload)
            .timeout(std::time::Duration::from_secs(30))
            .send()
            .await;
        
        match response {
            Ok(resp) if resp.status().is_success() => {
                let result: serde_json::Value = resp.json().await.unwrap_or_default();
                println!(
                    "{} Results submitted to dashboard!",
                    "✓".green().bold()
                );
                if let Some(resp_scan_id) = result.get("scan_id").or(result.get("id")) {
                    let scan_id_str = if let Some(s) = resp_scan_id.as_str() {
                        s.to_string()
                    } else {
                        resp_scan_id.to_string()
                    };
                    println!(
                        "  {} {}/dashboard/scans/{}",
                        "View at:".blue(),
                        base_url,
                        scan_id_str
                    );
                }
            }
            Ok(resp) => {
                let status = resp.status();
                let error_text = resp.text().await.unwrap_or_default();
                println!(
                    "{} Failed to submit results ({}): {}",
                    "⚠".yellow(),
                    status,
                    error_text.chars().take(200).collect::<String>()
                );
            }
            Err(e) => {
                println!(
                    "{} Could not reach KyberCheck API: {}",
                    "⚠".yellow(),
                    e.to_string().chars().take(100).collect::<String>()
                );
            }
        }
    }

    // Exit with error if vulnerabilities found and fail_on_vuln is set
    if fail_on_vuln && !results.vulnerabilities.is_empty() {
        std::process::exit(1);
    }

    Ok(())
}

async fn run_remote_scan(
    url: String,
    api_key: Option<String>,
    branch: Option<String>,
    output: Option<PathBuf>,
    fail_on_vuln: bool,
    min_severity: String,
    exclude: Vec<String>,
    languages: Option<Vec<String>>,
    keep: bool,
    format: &str,
) -> Result<()> {
    // Print the banner
    print_banner();

    // Check for API key
    let api_key = match api_key {
        Some(key) if !key.is_empty() => key,
        _ => {
            print_error(
                "API key required",
                "You must provide an API key to use KyberCheck.",
                Some("Set the KYBERCHECK_API_KEY environment variable or use --api-key"),
                Some("https://kybercheck.com/dashboard/settings/api-keys"),
            );
            std::process::exit(1);
        }
    };

    // Validate the API key format first
    if !api_key.starts_with("kc_") {
        print_error(
            "Invalid API key format",
            "API keys should start with 'kc_' prefix.",
            Some("Make sure you copied the entire API key from your dashboard."),
            Some("https://kybercheck.com/dashboard/settings/api-keys"),
        );
        std::process::exit(1);
    }

    // Validate API key with server
    println!("{}", "🔐 Validating API key...".dimmed());
    match validate_api_key(&api_key).await {
        Ok(true) => {
            println!("{}", "✓ API key validated".green());
        }
        Ok(false) => {
            print_error(
                "Invalid or expired API key",
                "The API key provided is invalid, expired, or has been revoked.",
                Some("Generate a new API key from your dashboard."),
                Some("https://kybercheck.com/dashboard/settings/api-keys"),
            );
            std::process::exit(1);
        }
        Err(e) => {
            let error_msg = e.to_string();
            if error_msg.contains("Invalid API key") || error_msg.contains("expired") || error_msg.contains("revoked") {
                print_error(
                    "Invalid or expired API key",
                    &error_msg,
                    Some("Generate a new API key from your dashboard."),
                    Some("https://kybercheck.com/dashboard/settings/api-keys"),
                );
            } else {
                print_error(
                    "Could not validate API key",
                    &error_msg,
                    Some("Check your internet connection and try again."),
                    Some("https://kybercheck.com/docs/troubleshooting"),
                );
            }
            std::process::exit(1);
        }
    }

    println!();
    print_compact_banner("Remote Repository Scan");

    // Normalize GitHub shorthand URLs
    let normalized_url = RemoteScanner::normalize_github_url(&url);
    
    // Show parsed info for GitHub URLs
    if let Some((owner, repo)) = RemoteScanner::parse_github_url(&normalized_url) {
        println!(
            "{} {}/{}",
            "📦 Repository:".blue(),
            owner.cyan(),
            repo.cyan()
        );
    }

    if let Some(ref b) = branch {
        println!("{} {}", "🌿 Branch:".blue(), b.cyan());
    }

    // Show language filter if specified
    if let Some(ref langs) = languages {
        println!(
            "{} {}",
            "🔍 Filtering languages:".blue(),
            langs.join(", ").cyan()
        );
    }

    println!();

    let config = AppConfig::new(true, true, min_severity, exclude, languages)?;
    let remote_scanner = RemoteScanner::new(config);

    // Clone and scan
    let (results, temp_dir) = remote_scanner
        .scan_remote(&normalized_url, branch.as_deref())
        .await?;

    // Select reporter based on format
    let reporter: Box<dyn Reporter> = match format {
        "json" => Box::new(JsonReporter::new()),
        _ => Box::new(ConsoleReporter::new()),
    };

    // Output results
    match output {
        Some(output_path) => {
            let report = reporter.generate(&results)?;
            std::fs::write(&output_path, report)?;
            println!(
                "\n{} {}",
                "Results written to:".green().bold(),
                output_path.display()
            );
        }
        None => {
            reporter.print(&results)?;
        }
    }

    // Summary
    println!("\n{}", "=".repeat(50).dimmed());
    println!(
        "{} {} vulnerabilities found",
        "Summary:".blue().bold(),
        results.vulnerabilities.len().to_string().yellow().bold()
    );
    println!(
        "  {} files scanned ({} lines)",
        results.files_scanned.to_string().cyan(),
        format_number(results.lines_scanned).cyan()
    );

    if results.has_db_impact {
        println!("  {} Database schema impacts detected", "⚠".yellow());
    }

    if results.has_api_impact {
        println!("  {} API payload impacts detected", "⚠".yellow());
    }

    // Handle temp directory
    if keep {
        let kept_path = temp_dir.into_path();
        println!(
            "\n{} {}",
            "Repository kept at:".green().bold(),
            kept_path.display().to_string().cyan()
        );
    } else {
        // temp_dir is dropped and cleaned up automatically
        println!("\n{}", "Cleaned up temporary clone".dimmed());
    }

    // Exit with error if vulnerabilities found and fail_on_vuln is set
    if fail_on_vuln && !results.vulnerabilities.is_empty() {
        std::process::exit(1);
    }

    Ok(())
}

async fn submit_results(
    results_path: PathBuf,
    api_key: Option<String>,
    api_url: String,
    repo_id: Option<String>,
) -> Result<()> {
    print_compact_banner("Submit Results");

    // Check for API key
    let api_key = match api_key {
        Some(key) if !key.is_empty() => key,
        _ => {
            print_error(
                "API key required",
                "You must provide an API key to submit results.",
                Some("Set the KYBERCHECK_API_KEY environment variable or use --api-key"),
                Some("https://kybercheck.com/dashboard/settings/api-keys"),
            );
            std::process::exit(1);
        }
    };

    // Validate the API key format first
    if !api_key.starts_with("kc_") {
        print_error(
            "Invalid API key format",
            "API keys should start with 'kc_' prefix.",
            Some("Make sure you copied the entire API key from your dashboard."),
            Some("https://kybercheck.com/dashboard/settings/api-keys"),
        );
        std::process::exit(1);
    }

    // Check if file exists
    if !results_path.exists() {
        print_error(
            "Results file not found",
            &format!("Could not find file: {}", results_path.display()),
            Some("Make sure you ran 'kybercheck scan' with --output first."),
            None,
        );
        std::process::exit(1);
    }

    println!("{} {}", "📄 File:".blue(), results_path.display().to_string().cyan());

    // Read results file
    let results_content = match std::fs::read_to_string(&results_path) {
        Ok(content) => content,
        Err(e) => {
            print_error(
                "Could not read results file",
                &e.to_string(),
                Some("Check file permissions and try again."),
                None,
            );
            std::process::exit(1);
        }
    };

    let mut results: types::ScanResults = match serde_json::from_str(&results_content) {
        Ok(r) => r,
        Err(e) => {
            print_error(
                "Invalid results file format",
                &e.to_string(),
                Some("Make sure the file is a valid KyberCheck scan output (JSON)."),
                None,
            );
            std::process::exit(1);
        }
    };

    // Set repo_id if provided
    if let Some(id) = repo_id {
        results.repo_id = Some(id);
    }

    println!("{}", "📤 Uploading results...".dimmed());

    // Prepare submission payload (anonymized - no source code)
    let payload = types::SubmissionPayload::from_results(&results);

    // Submit to API
    let client = reqwest::Client::new();
    let response = client
        .post(format!("{}/api/v1/scans", api_url))
        .header("Authorization", format!("Bearer {}", api_key))
        .header("Content-Type", "application/json")
        .json(&payload)
        .timeout(std::time::Duration::from_secs(30))
        .send()
        .await;

    match response {
        Ok(resp) if resp.status().is_success() => {
            let result: serde_json::Value = resp.json().await?;
            println!(
                "\n{} Results submitted successfully!",
                "✓".green().bold()
            );
            if let Some(scan_id) = result.get("scan_id") {
                let scan_id_str = if let Some(s) = scan_id.as_str() {
                    s.to_string()
                } else {
                    scan_id.to_string()
                };
                println!("  {} {}", "Scan ID:".blue(), scan_id_str.cyan());
                println!(
                    "  {} {}/dashboard/scans/{}",
                    "View at:".blue(),
                    API_BASE_URL,
                    scan_id_str
                );
            }
        }
        Ok(resp) => {
            let status = resp.status();
            let error_text = resp.text().await.unwrap_or_default();
            
            if status.as_u16() == 401 {
                print_error(
                    "Authentication failed",
                    "Your API key is invalid or expired.",
                    Some("Generate a new API key from your dashboard."),
                    Some("https://kybercheck.com/dashboard/settings/api-keys"),
                );
            } else if status.as_u16() == 403 {
                print_error(
                    "Permission denied",
                    "Your API key doesn't have permission to submit scans.",
                    Some("Make sure your API key has the 'scan:write' scope."),
                    Some("https://kybercheck.com/dashboard/settings/api-keys"),
                );
            } else {
                print_error(
                    "Submission failed",
                    &format!("Server returned {} - {}", status, error_text),
                    Some("Try again or contact support if the issue persists."),
                    Some("https://kybercheck.com/support"),
                );
            }
            std::process::exit(1);
        }
        Err(e) => {
            if e.is_timeout() {
                print_error(
                    "Request timed out",
                    "The server took too long to respond.",
                    Some("Check your internet connection and try again."),
                    None,
                );
            } else if e.is_connect() {
                print_error(
                    "Connection failed",
                    "Could not connect to KyberCheck servers.",
                    Some("Check your internet connection and try again."),
                    None,
                );
            } else {
                print_error(
                    "Upload failed",
                    &e.to_string(),
                    Some("Try again or contact support if the issue persists."),
                    Some("https://kybercheck.com/support"),
                );
            }
            std::process::exit(1);
        }
    }

    Ok(())
}

fn init_config(force: bool) -> Result<()> {
    let config_path = PathBuf::from(".kybercheck.toml");

    if config_path.exists() && !force {
        anyhow::bail!(
            "Configuration file already exists. Use --force to overwrite."
        );
    }

    let default_config = r#"# KyberCheck Configuration

# Scan settings
[scan]
# Include transitive dependency analysis
analyze_dependencies = true
# Analyze database schema impacts
analyze_db_impact = true
# Minimum severity to report (low, medium, high, critical)
min_severity = "low"

# Patterns to exclude from scanning
exclude = [
    "node_modules/**",
    "vendor/**",
    "target/**",
    ".git/**",
    "**/*.min.js",
    "**/dist/**",
]

# API settings (for CI/CD integration)
[api]
# API endpoint URL
url = "https://api.kybercheck.io"
# API key (use environment variable KYBERCHECK_API_KEY instead for security)
# api_key = ""

# Repository settings
[repo]
# Repository identifier (auto-detected from git if not set)
# id = ""
"#;

    std::fs::write(&config_path, default_config)?;
    println!(
        "{} Configuration file created: {}",
        "✓".green().bold(),
        config_path.display()
    );

    Ok(())
}

fn show_info() -> Result<()> {
    print_banner();

    println!("{}", "📋 Features:".blue().bold());
    println!("  {} Parallel scanning (multi-threaded)", "✓".green());
    println!("  {} Remote Git repository scanning", "✓".green());
    println!("  {} 20+ programming languages supported", "✓".green());
    println!("  {} API key required for authentication", "✓".green());

    println!("\n{}", "Supported Languages:".blue().bold());
    let languages = [
        ("JavaScript", "javascript, js", ".js, .jsx, .mjs, .cjs"),
        ("TypeScript", "typescript, ts", ".ts, .tsx, .mts, .cts"),
        ("Python", "python, py", ".py, .pyw, .pyi"),
        ("Go", "go", ".go"),
        ("Java", "java", ".java"),
        ("Kotlin", "kotlin", ".kt, .kts"),
        ("Scala", "scala", ".scala, .sc"),
        ("Groovy", "groovy", ".groovy, .gvy"),
        ("Rust", "rust", ".rs"),
        ("C", "c", ".c, .h"),
        ("C++", "cpp, c++", ".cpp, .cc, .cxx, .hpp"),
        ("C#", "csharp, c#, cs", ".cs, .csx"),
        ("PHP", "php", ".php, .phtml"),
        ("Ruby", "ruby, rb", ".rb, .rbw, .rake"),
        ("Swift", "swift", ".swift"),
        ("Objective-C", "objectivec, objc", ".m, .mm"),
        ("Shell/Bash", "shell, sh, bash", ".sh, .bash, .zsh"),
        ("Perl", "perl", ".pl, .pm"),
        ("Lua", "lua", ".lua"),
        ("Dart", "dart", ".dart"),
    ];
    for (lang, filter_names, exts) in languages {
        println!("  {} {} [{}]: {}", "•".cyan(), lang, filter_names.dimmed(), exts.dimmed());
    }

    println!("\n{}", "Usage Examples:".blue().bold());
    println!("  {} kybercheck scan ./project", "Local scan:".green());
    println!("  {} kybercheck scan -l rust,python ./project", "Filter langs:".green());
    println!("  {} kybercheck remote owner/repo", "GitHub scan:".green());
    println!("  {} kybercheck remote https://github.com/org/repo.git", "Full URL:".green());
    println!("  {} kybercheck remote owner/repo --branch main --keep", "With options:".green());

    println!("\n{}", "Detected Vulnerabilities:".blue().bold());
    let vulns = [
        ("RSA (all key sizes)", "Asymmetric encryption vulnerable to Shor's algorithm"),
        ("ECDSA/ECDH", "Elliptic curve cryptography vulnerable to quantum attacks"),
        ("DSA", "Digital Signature Algorithm vulnerable to quantum attacks"),
        ("DH (Diffie-Hellman)", "Key exchange vulnerable to quantum attacks"),
        ("SHA-1", "Weak hash function (not quantum-specific but flagged)"),
        ("MD5", "Broken hash function"),
        ("3DES/DES", "Weak symmetric encryption"),
        ("RC4", "Broken stream cipher"),
    ];
    for (vuln, desc) in vulns {
        println!("  {} {} - {}", "•".yellow(), vuln.red(), desc.dimmed());
    }

    println!("\n{}", "Impact Analysis:".blue().bold());
    let impacts = [
        "Database schema conflicts (key size changes)",
        "API payload bloat warnings",
        "Architectural refactoring requirements (RSA → KEM)",
        "Certificate/PKI infrastructure changes",
    ];
    for impact in impacts {
        println!("  {} {}", "•".cyan(), impact);
    }

    println!("\n{}", "NIST PQC Standards (Target Migration):".blue().bold());
    let standards = [
        ("CRYSTALS-Kyber (ML-KEM)", "Key Encapsulation Mechanism"),
        ("CRYSTALS-Dilithium (ML-DSA)", "Digital Signatures"),
        ("SPHINCS+", "Hash-based Signatures"),
        ("FALCON", "Lattice-based Signatures"),
    ];
    for (name, purpose) in standards {
        println!("  {} {} - {}", "•".green(), name.green(), purpose.dimmed());
    }

    Ok(())
}
