#![allow(clippy::print_stdout)]
#![allow(clippy::print_stderr)]
#![allow(clippy::cast_precision_loss)]
#![allow(clippy::cast_possible_truncation)]
#![allow(clippy::unwrap_used)]
#![allow(clippy::uninlined_format_args)]
#![allow(clippy::format_push_string)]
#![allow(clippy::match_same_arms)]
#![allow(clippy::fn_params_excessive_bools)]
#![allow(clippy::too_many_lines)]
#![allow(clippy::redundant_field_names)]
#![allow(clippy::too_many_arguments)]
#![allow(clippy::collapsible_else_if)]
#![allow(clippy::field_reassign_with_default)]
#![allow(clippy::format_in_format_args)]
#![allow(clippy::items_after_statements)]
#![allow(dead_code)]

use anyhow::Result;
use clap::{Parser, Subcommand};
// use colored::Colorize; // Unused after refactoring
use ruchy::{runtime::repl::Repl, Parser as RuchyParser};
use std::fs;
use std::io::{self, IsTerminal, Read};
use std::path::{Path, PathBuf};


mod handlers;
use handlers::{
    handle_parse_command, handle_transpile_command, handle_run_command,
    handle_eval_command, handle_file_execution, handle_stdin_input, handle_repl_command,
    handle_compile_command, handle_check_command, handle_test_command, handle_complex_command
};

/// Configuration for code formatting
#[derive(Debug, Clone)]
struct FormatConfig {
    #[allow(dead_code)]
    line_width: usize,
    indent: usize,
    use_tabs: bool,
}

impl Default for FormatConfig {
    fn default() -> Self {
        Self {
            line_width: 100,
            indent: 4,
            use_tabs: false,
        }
    }
}

#[derive(Parser)]
#[command(name = "ruchy")]
#[command(author, version, about = "The Ruchy programming language", long_about = None)]
struct Cli {
    /// Evaluate a one-liner expression
    #[arg(short = 'e', long = "eval", value_name = "EXPR")]
    eval: Option<String>,

    /// Output format for evaluation results (text, json)
    #[arg(long, default_value = "text")]
    format: String,

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

    /// Script file to execute (alternative to subcommands)
    file: Option<PathBuf>,

    #[command(subcommand)]
    command: Option<Commands>,
}

#[derive(Subcommand)]
enum Commands {
    /// Start the interactive REPL
    Repl {
        /// Record REPL session to a .replay file
        #[arg(long, value_name = "FILE")]
        record: Option<PathBuf>,
    },

    /// Parse a Ruchy file and show the AST
    Parse {
        /// The file to parse
        file: PathBuf,
    },

    /// Transpile a Ruchy file to Rust
    Transpile {
        /// The file to transpile
        file: PathBuf,

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

        /// Use minimal codegen for self-hosting (direct Rust mapping, no optimization)
        #[arg(long)]
        minimal: bool,
    },

    /// Compile and run a Ruchy file
    Run {
        /// The file to run
        file: PathBuf,
    },
    
    /// Compile a Ruchy file to a standalone binary (RUCHY-0801)
    Compile {
        /// The file to compile
        file: PathBuf,
        
        /// Output binary path
        #[arg(short, long, default_value = "a.out")]
        output: PathBuf,
        
        /// Optimization level (0-3, or 's' for size)
        #[arg(short = 'O', long, default_value = "2")]
        opt_level: String,
        
        /// Strip debug symbols
        #[arg(long)]
        strip: bool,
        
        /// Static linking
        #[arg(long)]
        static_link: bool,
        
        /// Target triple (e.g., x86_64-unknown-linux-gnu)
        #[arg(long)]
        target: Option<String>,
    },

    /// Check syntax without running
    Check {
        /// The file to check
        file: PathBuf,

        /// Watch for changes and re-check automatically
        #[arg(long)]
        watch: bool,
    },

    /// Run tests for Ruchy code with optional coverage reporting
    Test {
        /// The test file or directory to run
        path: Option<PathBuf>,

        /// Watch for changes and re-run tests automatically
        #[arg(long)]
        watch: bool,

        /// Show verbose output
        #[arg(long)]
        verbose: bool,

        /// Filter tests by name pattern
        #[arg(long)]
        filter: Option<String>,

        /// Generate coverage report
        #[arg(long)]
        coverage: bool,

        /// Coverage output format (text, html, json)
        #[arg(long, default_value = "text")]
        coverage_format: String,

        /// Run tests in parallel
        #[arg(long)]
        parallel: bool,

        /// Minimum coverage threshold (fail if below)
        #[arg(long)]
        threshold: Option<f64>,

        /// Output format for test results (text, json, junit)
        #[arg(long, default_value = "text")]
        format: String,
    },

    /// Generate coverage report for Ruchy code
    Coverage {
        /// The file or directory to analyze  
        path: PathBuf,

        /// Minimum coverage threshold (fail if below)
        #[arg(long)]
        threshold: Option<f64>,

        /// Output format for coverage report (text, html, json)
        #[arg(long, default_value = "text")]
        format: String,

        /// Show verbose coverage output
        #[arg(long)]
        verbose: bool,
    },

    /// Show AST for a file (Enhanced for v0.9.12)
    Ast {
        /// The file to parse
        file: PathBuf,

        /// Output AST in JSON format for tooling integration
        #[arg(long)]
        json: bool,

        /// Generate visual AST graph in DOT format
        #[arg(long)]
        graph: bool,

        /// Calculate and show complexity metrics
        #[arg(long)]
        metrics: bool,

        /// Perform symbol table analysis
        #[arg(long)]
        symbols: bool,

        /// Analyze module dependencies
        #[arg(long)]
        deps: bool,

        /// Show verbose analysis output
        #[arg(long)]
        verbose: bool,

        /// Output file for graph/analysis results
        #[arg(long)]
        output: Option<PathBuf>,
    },

    /// Formal verification and correctness analysis (RUCHY-0754)
    Provability {
        /// The file to analyze
        file: PathBuf,

        /// Perform full formal verification
        #[arg(long)]
        verify: bool,

        /// Contract verification (pre/post-conditions, invariants)
        #[arg(long)]
        contracts: bool,

        /// Loop invariant checking
        #[arg(long)]
        invariants: bool,

        /// Termination analysis for loops and recursion
        #[arg(long)]
        termination: bool,

        /// Array bounds checking and memory safety
        #[arg(long)]
        bounds: bool,

        /// Show verbose verification output
        #[arg(long)]
        verbose: bool,

        /// Output file for verification results
        #[arg(long)]
        output: Option<PathBuf>,
    },

    /// Performance analysis and `BigO` complexity detection (RUCHY-0755)
    Runtime {
        /// The file to analyze
        file: PathBuf,

        /// Perform detailed execution profiling
        #[arg(long)]
        profile: bool,

        /// Automatic `BigO` algorithmic complexity analysis
        #[arg(long)]
        bigo: bool,

        /// Benchmark execution with statistical analysis
        #[arg(long)]
        bench: bool,

        /// Compare performance between two files
        #[arg(long)]
        compare: Option<PathBuf>,

        /// Memory usage and allocation analysis
        #[arg(long)]
        memory: bool,

        /// Show verbose performance output
        #[arg(long)]
        verbose: bool,

        /// Output file for performance results
        #[arg(long)]
        output: Option<PathBuf>,
    },

    /// Unified quality scoring (RUCHY-0810)
    Score {
        /// The file or directory to score
        path: PathBuf,

        /// Analysis depth (shallow/standard/deep)
        #[arg(long, default_value = "standard")]
        depth: String,

        /// Fast feedback mode (AST-only, <100ms)
        #[arg(long)]
        fast: bool,

        /// Deep analysis for CI (complete, <30s)
        #[arg(long)]
        deep: bool,

        /// Watch mode with progressive refinement
        #[arg(long)]
        watch: bool,

        /// Explain score changes from baseline
        #[arg(long)]
        explain: bool,

        /// Baseline branch/commit for comparison
        #[arg(long)]
        baseline: Option<String>,

        /// Minimum score threshold (0.0-1.0)
        #[arg(long)]
        min: Option<f64>,

        /// Configuration file
        #[arg(long)]
        config: Option<PathBuf>,

        /// Output format (text/json/html)
        #[arg(long, default_value = "text")]
        format: String,

        /// Verbose output
        #[arg(long)]
        verbose: bool,

        /// Output file for score report
        #[arg(long)]
        output: Option<PathBuf>,
    },

    /// Quality gate enforcement (RUCHY-0815)
    QualityGate {
        /// The file or directory to check
        path: PathBuf,

        /// Configuration file (.ruchy/score.toml)
        #[arg(long)]
        config: Option<PathBuf>,

        /// Analysis depth (shallow/standard/deep)
        #[arg(long, default_value = "standard")]
        depth: String,

        /// Fail fast on first violation
        #[arg(long)]
        fail_fast: bool,

        /// Output format (console/json/junit)
        #[arg(long, default_value = "console")]
        format: String,

        /// Export CI/CD results
        #[arg(long)]
        export: Option<PathBuf>,

        /// Run in CI mode (strict thresholds)
        #[arg(long)]
        ci: bool,

        /// Show detailed violation information
        #[arg(long)]
        verbose: bool,
    },

    /// Format Ruchy source code (Enhanced for v0.9.12)
    Fmt {
        /// The file to format
        file: PathBuf,

        /// Format all files in project
        #[arg(long)]
        all: bool,

        /// Check if files are formatted without modifying them
        #[arg(long)]
        check: bool,

        /// Write formatted output to stdout instead of modifying files
        #[arg(long)]
        stdout: bool,

        /// Show diff of changes
        #[arg(long)]
        diff: bool,

        /// Configuration file for formatting rules
        #[arg(long)]
        config: Option<PathBuf>,

        /// Maximum line width for formatting
        #[arg(long, default_value = "100")]
        line_width: usize,

        /// Indentation size (spaces)
        #[arg(long, default_value = "4")]
        indent: usize,

        /// Use tabs instead of spaces for indentation
        #[arg(long)]
        use_tabs: bool,
    },

    /// Generate documentation from Ruchy source code
    Doc {
        /// The file or directory to document
        path: PathBuf,

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

        /// Documentation format (html, markdown, json)
        #[arg(long, default_value = "html")]
        format: String,

        /// Include private items in documentation
        #[arg(long)]
        private: bool,

        /// Open documentation in browser after generation
        #[arg(long)]
        open: bool,

        /// Generate documentation for all files in project
        #[arg(long)]
        all: bool,

        /// Show verbose output
        #[arg(long)]
        verbose: bool,
    },

    /// Benchmark Ruchy code performance
    Bench {
        /// The file to benchmark
        file: PathBuf,

        /// Number of iterations to run
        #[arg(long, default_value = "100")]
        iterations: usize,

        /// Number of warmup iterations
        #[arg(long, default_value = "10")]
        warmup: usize,

        /// Output format (text, json, csv)
        #[arg(long, default_value = "text")]
        format: String,

        /// Save results to file
        #[arg(long)]
        output: Option<PathBuf>,

        /// Show verbose output including individual runs
        #[arg(long)]
        verbose: bool,
    },

    /// Lint Ruchy source code for issues and style violations (Enhanced for v0.9.12)
    Lint {
        /// The file to lint (ignored if --all is used)
        file: Option<PathBuf>,

        /// Lint all files in project
        #[arg(long)]
        all: bool,

        /// Auto-fix issues where possible
        #[arg(long)]
        fix: bool,

        /// Strict mode with all rules enabled
        #[arg(long)]
        strict: bool,

        /// Show additional context for violations
        #[arg(long)]
        verbose: bool,

        /// Output format (text, json)
        #[arg(long, default_value = "text")]
        format: String,

        /// Specific rule categories to check (comma-separated: unused,style,complexity,safety,performance)
        #[arg(long)]
        rules: Option<String>,

        /// Fail on warnings as well as errors
        #[arg(long)]
        deny_warnings: bool,

        /// Maximum allowed complexity for functions
        #[arg(long, default_value = "10")]
        max_complexity: usize,

        /// Path to custom lint rules configuration file
        #[arg(long)]
        config: Option<PathBuf>,

        /// Generate default lint configuration file
        #[arg(long)]
        init_config: bool,
    },

    /// Add a package dependency
    Add {
        /// Package name to add
        package: String,
        /// Specific version to add (default: latest)
        #[arg(long)]
        version: Option<String>,
        /// Add as development dependency
        #[arg(long)]
        dev: bool,
        /// Registry URL to use
        #[arg(long, default_value = "https://ruchy.dev/registry")]
        registry: String,
    },

    /// Publish a package to the registry
    Publish {
        /// Registry URL to publish to
        #[arg(long, default_value = "https://ruchy.dev/registry")]
        registry: String,
        /// Package version to publish (reads from Ruchy.toml if not specified)
        #[arg(long)]
        version: Option<String>,
        /// Perform a dry run without actually publishing
        #[arg(long)]
        dry_run: bool,
        /// Allow publishing dirty working directory
        #[arg(long)]
        allow_dirty: bool,
    },
    
    /// Start MCP server for real-time quality analysis (RUCHY-0811)
    Mcp {
        /// Server name for MCP identification
        #[arg(long, default_value = "ruchy-mcp")]
        name: String,
        
        /// Enable streaming updates
        #[arg(long)]
        streaming: bool,
        
        /// Session timeout in seconds
        #[arg(long, default_value = "3600")]
        timeout: u64,
        
        /// Minimum quality score threshold
        #[arg(long, default_value = "0.8")]
        min_score: f64,
        
        /// Maximum complexity threshold
        #[arg(long, default_value = "10")]
        max_complexity: u32,
        
        /// Enable verbose logging
        #[arg(short, long)]
        verbose: bool,
        
        /// Configuration file path
        #[arg(short, long)]
        config: Option<PathBuf>,
    },

    /// Hardware-aware optimization analysis (RUCHY-0816)
    Optimize {
        /// The file to analyze for optimization opportunities
        file: PathBuf,

        /// Hardware profile to use (detect, intel, amd, arm)
        #[arg(long, default_value = "detect")]
        hardware: String,

        /// Analysis depth (quick, standard, deep)
        #[arg(long, default_value = "standard")]
        depth: String,

        /// Show cache behavior analysis
        #[arg(long)]
        cache: bool,

        /// Show branch prediction analysis
        #[arg(long)]
        branches: bool,

        /// Show vectorization opportunities
        #[arg(long)]
        vectorization: bool,

        /// Show abstraction cost analysis
        #[arg(long)]
        abstractions: bool,

        /// Benchmark hardware characteristics
        #[arg(long)]
        benchmark: bool,

        /// Output format (text, json, html)
        #[arg(long, default_value = "text")]
        format: String,

        /// Save analysis to file
        #[arg(long)]
        output: Option<PathBuf>,

        /// Show verbose optimization details
        #[arg(long)]
        verbose: bool,

        /// Minimum impact threshold for recommendations (0.0-1.0)
        #[arg(long, default_value = "0.05")]
        threshold: f64,
    },

    /// Actor observatory for live system introspection (RUCHY-0817)
    #[command(name = "actor:observe")]
    ActorObserve {
        /// Actor system configuration file
        #[arg(long)]
        config: Option<PathBuf>,

        /// Observatory refresh interval in milliseconds
        #[arg(long, default_value = "1000")]
        refresh_interval: u64,

        /// Maximum number of message traces to display
        #[arg(long, default_value = "50")]
        max_traces: usize,

        /// Maximum number of actors to display
        #[arg(long, default_value = "20")]
        max_actors: usize,

        /// Enable deadlock detection
        #[arg(long)]
        enable_deadlock_detection: bool,

        /// Deadlock detection interval in milliseconds
        #[arg(long, default_value = "1000")]
        deadlock_interval: u64,

        /// Start in a specific view mode (overview, actors, messages, metrics, deadlocks)
        #[arg(long, default_value = "overview")]
        start_mode: String,

        /// Disable color output
        #[arg(long)]
        no_color: bool,

        /// Output format (interactive, json, text)
        #[arg(long, default_value = "interactive")]
        format: String,

        /// Export observations to file
        #[arg(long)]
        export: Option<PathBuf>,

        /// Duration to observe in seconds (0 for infinite)
        #[arg(long, default_value = "0")]
        duration: u64,

        /// Show verbose output
        #[arg(long)]
        verbose: bool,

        /// Add message filter by actor name pattern
        #[arg(long)]
        filter_actor: Option<String>,

        /// Add message filter for failed messages only
        #[arg(long)]
        filter_failed: bool,

        /// Add message filter for delayed messages (minimum microseconds)
        #[arg(long)]
        filter_slow: Option<u64>,
    },

    /// Dataflow debugger for `DataFrame` pipeline debugging (RUCHY-0818)
    #[command(name = "dataflow:debug")]
    DataflowDebug {
        /// Pipeline configuration file
        #[arg(long)]
        config: Option<PathBuf>,
        
        /// Maximum rows to materialize per stage
        #[arg(long, default_value = "1000")]
        max_rows: usize,
        
        /// Auto-materialize data at each stage
        #[arg(long)]
        auto_materialize: bool,
        
        /// Enable performance profiling
        #[arg(long, default_value = "true")]
        enable_profiling: bool,
        
        /// Stage execution timeout in milliseconds
        #[arg(long, default_value = "30000")]
        timeout: u64,
        
        /// Enable memory tracking
        #[arg(long)]
        track_memory: bool,
        
        /// Compute diffs between stages
        #[arg(long)]
        compute_diffs: bool,
        
        /// Sample rate for large datasets (0.0-1.0)
        #[arg(long, default_value = "1.0")]
        sample_rate: f64,
        
        /// UI refresh interval in milliseconds
        #[arg(long, default_value = "1000")]
        refresh_interval: u64,
        
        /// Disable color output
        #[arg(long)]
        no_color: bool,
        
        /// Output format (interactive, json, text)
        #[arg(long, default_value = "interactive")]
        format: String,
        
        /// Export debug data to file
        #[arg(long)]
        export: Option<PathBuf>,
        
        /// Show verbose debugging output
        #[arg(long)]
        verbose: bool,
        
        /// Add breakpoint at stage (can be used multiple times)
        #[arg(long)]
        breakpoint: Vec<String>,
        
        /// Start mode (overview, stages, data, metrics, history)
        #[arg(long, default_value = "overview")]
        start_mode: String,
    },

    /// WebAssembly component toolkit (RUCHY-0819)
    Wasm {
        /// The source file to compile to WASM
        file: PathBuf,
        
        /// Output file for the WASM component
        #[arg(short, long)]
        output: Option<PathBuf>,
        
        /// Target platform (wasm32, wasi, browser, nodejs, cloudflare-workers)
        #[arg(long, default_value = "wasm32")]
        target: String,
        
        /// Generate WIT interface definition
        #[arg(long)]
        wit: bool,
        
        /// Deploy to target platform
        #[arg(long)]
        deploy: bool,
        
        /// Deployment target (cloudflare, fastly, aws-lambda, vercel, deno)
        #[arg(long)]
        deploy_target: Option<String>,
        
        /// Analyze portability across platforms
        #[arg(long)]
        portability: bool,
        
        /// Optimization level (none, O1, O2, O3, Os, Oz)
        #[arg(long, default_value = "O2")]
        opt_level: String,
        
        /// Include debug information
        #[arg(long)]
        debug: bool,
        
        /// Enable SIMD instructions
        #[arg(long)]
        simd: bool,
        
        /// Enable threads and atomics
        #[arg(long)]
        threads: bool,
        
        /// Enable component model
        #[arg(long, default_value = "true")]
        component_model: bool,
        
        /// Component name
        #[arg(long)]
        name: Option<String>,
        
        /// Component version
        #[arg(long, default_value = "0.1.0")]
        version: String,
        
        /// Show verbose output
        #[arg(long)]
        verbose: bool,
    },
    
    /// Interactive theorem prover (RUCHY-0820)
    Prove {
        /// The file to verify (optional, starts REPL if not provided)
        file: Option<PathBuf>,
        
        /// SMT backend (z3, cvc5, yices2)
        #[arg(long, default_value = "z3")]
        backend: String,
        
        /// Enable ML-powered tactic suggestions
        #[arg(long)]
        ml_suggestions: bool,
        
        /// Timeout for SMT queries in milliseconds
        #[arg(long, default_value = "5000")]
        timeout: u64,
        
        /// Load proof script
        #[arg(long)]
        script: Option<PathBuf>,
        
        /// Export proof to file
        #[arg(long)]
        export: Option<PathBuf>,
        
        /// Non-interactive mode (check proofs only)
        #[arg(long)]
        check: bool,
        
        /// Generate counterexamples for failed proofs
        #[arg(long)]
        counterexample: bool,
        
        /// Show verbose proof output
        #[arg(long)]
        verbose: bool,
        
        /// Output format (text, json, coq, lean)
        #[arg(long, default_value = "text")]
        format: String,
    },

    /// Convert REPL replay files to regression tests
    ReplayToTests {
        /// Input replay file or directory containing .replay files
        input: PathBuf,

        /// Output test file (defaults to `tests/generated_from_replays.rs`)
        #[arg(short, long)]
        output: Option<PathBuf>,

        /// Include property tests for invariants
        #[arg(long)]
        property_tests: bool,

        /// Include performance benchmarks
        #[arg(long)]
        benchmarks: bool,

        /// Test timeout in milliseconds
        #[arg(long, default_value = "5000")]
        timeout: u64,
    },
}

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

    // Handle one-liner evaluation with -e flag
    if let Some(expr) = cli.eval {
        return handle_eval_command(&expr, cli.verbose, &cli.format);
    }

    // Handle script file execution (without subcommand)
    if let Some(file) = cli.file {
        return handle_file_execution(&file);
    }

    // Check if stdin has input (piped mode) - but only when no command or file is specified
    if !io::stdin().is_terminal() && cli.command.is_none() {
        let mut input = String::new();
        io::stdin().read_to_string(&mut input)?;

        if !input.trim().is_empty() {
            return handle_stdin_input(&input);
        }
    }

    // Handle subcommands
    match cli.command {
        Some(Commands::Repl { record }) => {
            handle_repl_command(record)?;
        }
        None => {
            handle_repl_command(None)?;
        }
        Some(Commands::Parse { file }) => {
            handle_parse_command(&file, cli.verbose)?;
        }
        Some(Commands::Transpile { file, output, minimal }) => {
            handle_transpile_command(&file, output.as_deref(), minimal, cli.verbose)?;
        }
        Some(Commands::Run { file }) => {
            handle_run_command(&file, cli.verbose)?;
        }
        Some(Commands::Compile { 
            file, 
            output, 
            opt_level, 
            strip, 
            static_link, 
            target 
        }) => {
            handle_compile_command(&file, output, opt_level, strip, static_link, target)?;
        }
        Some(Commands::Check { file, watch }) => {
            handle_check_command(&file, watch)?;
        }
        Some(Commands::Test {
            path,
            watch,
            verbose,
            filter,
            coverage,
            coverage_format,
            parallel,
            threshold,
            format,
        }) => {
            handle_test_command(
                path,
                watch,
                verbose,
                filter.as_deref(),
                coverage,
                &coverage_format,
                usize::from(parallel),
                threshold.unwrap_or(0.0),
                &format,
            )?;
        }
        Some(command) => {
            handle_advanced_command(command)?;
        }
    } 

    Ok(())
}

fn handle_advanced_command(command: Commands) -> Result<()> {
    // Delegate to the existing handle_complex_command from cli module
    handle_complex_command(command)
}

fn run_file(file: &Path) -> Result<()> {
    let source = fs::read_to_string(file)?;

    // Use REPL to evaluate the file
    let mut repl = Repl::new()?;
    match repl.eval(&source) {
        Ok(result) => {
            // Only print non-unit results
            if result != "Unit" && result != "()" {
                println!("{result}");
            }
            Ok(())
        }
        Err(e) => {
            eprintln!("Error: {e}");
            std::process::exit(1);
        }
    }
}

/// Check syntax of a file
fn check_syntax(file: &Path) -> Result<()> {
    use colored::Colorize;
    let source = fs::read_to_string(file)?;
    let mut parser = RuchyParser::new(&source);
    match parser.parse() {
        Ok(_) => {
            println!("{}", "✓ Syntax is valid".green());
            Ok(())
        }
        Err(e) => {
            eprintln!("{}", format!("✗ Syntax error: {e}").red());
            std::process::exit(1);
        }
    }
}

