use clap::Parser;

use nexus_core::cli::{Cli, Command};
use nexus_core::{module_a, module_b, module_c, module_d, module_e, module_f};

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

    match cli.command {
        Command::ModuleA(args) => {
            let stats = module_a::run(module_a::ModuleAConfig {
                payload_bytes: args.payload_bytes,
                chunk_bytes: args.chunk_bytes,
            })?;
            if args.json {
                println!("{}", stats.to_json());
            } else {
                println!("Module A complete");
                println!("  payload_bytes: {}", stats.payload_bytes);
                println!("  chunk_bytes: {}", stats.chunk_bytes);
                println!("  chunks: {}", stats.chunks);
                println!("  elapsed_ms: {:.3}", stats.elapsed_ms);
                println!("  throughput_mb_s: {:.3}", stats.throughput_mb_s);
                println!("  total_output_bytes: {}", stats.total_output_bytes);
                println!("  hot_loop_allocations: {}", stats.hot_loop_allocations);
                println!("  crc_fold: {}", stats.crc_fold);
            }
        }
        Command::ModuleB(args) => {
            let stats = module_b::run_parent(module_b::ModuleBConfig {
                memfd_bytes: args.memfd_bytes,
                socket_path: args.socket_path,
                marker: args.marker,
            })?;
            if args.json {
                println!("{}", stats.to_json());
            } else {
                println!("Module B complete");
                println!("  memfd_bytes: {}", stats.memfd_bytes);
                println!("  handoff_latency_ms: {:.3}", stats.handoff_latency_ms);
                println!("  marker_ok: {}", stats.marker_ok);
                println!("  socket_path: {}", stats.socket_path.display());
            }
        }
        Command::ModuleCWrite(args) => {
            let stats = module_c::run_writer(module_c::ModuleCWriteConfig {
                records: args.records,
                wal_path: args.wal_path,
            })?;
            if args.json {
                println!("{}", stats.to_json());
            } else {
                println!("Module C writer complete");
                println!("  records_written: {}", stats.records_written);
                println!("  elapsed_ms: {:.3}", stats.elapsed_ms);
                println!("  file_size_bytes: {}", stats.file_size_bytes);
                println!("  wal_path: {}", stats.wal_path.display());
            }
        }
        Command::ModuleCRead(args) => {
            let stats = module_c::run_reader(module_c::ModuleCReadConfig {
                wal_path: args.wal_path,
                expect_records: args.expect_records,
            })?;
            if args.json {
                println!("{}", stats.to_json());
            } else {
                println!("Module C reader complete");
                println!("  records_read: {}", stats.records_read);
                println!("  elapsed_ms: {:.3}", stats.elapsed_ms);
                println!("  defaults_ok: {}", stats.defaults_ok);
                println!("  zero_copy_ok: {}", stats.zero_copy_ok);
                println!("  read_loop_allocations: {}", stats.read_loop_allocations);
                println!("  wal_path: {}", stats.wal_path.display());
            }
        }
        Command::ModuleDAppend(args) => {
            let stats = module_d::run(module_d::ModuleDConfig {
                target_path: args.target_path,
                total_bytes: args.total_bytes,
                group_bytes: args.group_bytes,
                request_bytes: args.request_bytes,
                producers: args.producers,
                seed: args.seed,
                allow_file_fallback: args.allow_file_fallback,
                require_io_uring: args.require_io_uring,
            })?;
            if args.json {
                println!("{}", stats.to_json());
            } else {
                println!("Module D complete");
                println!("  mode: {}", stats.mode);
                println!("  target_path: {}", stats.target_path.display());
                println!("  bytes_written: {}", stats.bytes_written);
                println!("  commits: {}", stats.commits);
                println!("  elapsed_ms: {:.3}", stats.elapsed_ms);
                println!("  throughput_mb_s: {:.3}", stats.throughput_mb_s);
                println!("  io_wait_pct: {:.3}", stats.io_wait_pct);
                println!("  alignment_violations: {}", stats.alignment_violations);
                println!("  write_errors: {}", stats.write_errors);
            }
        }
        Command::ModuleEFst(args) => {
            let stats = module_e::run_fst(module_e::ModuleEFstConfig {
                keys: args.keys,
                lookups: args.lookups,
                list_queries: args.list_queries,
                index_path: args.index_path,
            })?;
            if args.json {
                println!("{}", stats.to_json());
            } else {
                println!("Module E (FST) complete");
                println!("  keys: {}", stats.keys);
                println!("  index_size_bytes: {}", stats.index_size_bytes);
                println!("  vm_rss_bytes: {}", stats.vm_rss_bytes);
                println!("  lookup_mean_ns: {:.2}", stats.lookup_mean_ns);
                println!("  list_seek_mean_ns: {:.2}", stats.list_seek_mean_ns);
            }
        }
        Command::ModuleETrie(args) => {
            let stats = module_e::run_trie(module_e::ModuleETrieConfig {
                keys: args.keys,
                lookups: args.lookups,
                list_queries: args.list_queries,
            })?;
            if args.json {
                println!("{}", stats.to_json());
            } else {
                println!("Module E (trie-rs) complete");
                println!("  keys: {}", stats.keys);
                println!("  vm_rss_bytes: {}", stats.vm_rss_bytes);
                println!("  lookup_mean_ns: {:.2}", stats.lookup_mean_ns);
                println!("  list_seek_mean_ns: {:.2}", stats.list_seek_mean_ns);
            }
        }
        Command::ModuleECompare(args) => {
            let stats = module_e::run_compare(module_e::ModuleECompareConfig {
                keys: args.keys,
                lookups: args.lookups,
                list_queries: args.list_queries,
                index_path: args.index_path,
            })?;
            if args.json {
                println!("{}", stats.to_json());
            } else {
                println!("Module E compare complete");
                println!("  recommendation: {}", stats.recommendation);
                println!("  fst_memory_target_met: {}", stats.fst.memory_target_met);
                println!("  trie_memory_target_met: {}", stats.trie.memory_target_met);
            }
        }
        Command::ModuleFServe(args) => {
            module_f::serve(module_f::ModuleFConfig {
                listen_addr: args.listen_addr,
                workers: args.workers,
                target_path: args.target_path,
                group_bytes: args.group_bytes,
                compaction_threshold: args.compaction_threshold,
                flush_interval_ms: args.flush_interval_ms,
                default_bucket: args.bucket,
                access_key: args.access_key,
                secret_key: args.secret_key,
                allow_file_fallback: args.allow_file_fallback,
                require_io_uring: args.require_io_uring,
            })?;
        }
        Command::ModuleBReceiverInternal(args) => {
            module_b::run_receiver_internal(module_b::ModuleBReceiverConfig {
                socket_path: args.socket_path,
                marker: args.marker,
                memfd_bytes: args.memfd_bytes,
            })?;
        }
    }

    Ok(())
}
