use anyhow::Result;
use clap::{Parser, Subcommand};
use tools_shared::find_config_path_warn_conflicts;

mod api_client;
mod handlers;
mod remote_ops;
mod ui_config;
use handlers::{
    BatchHandler, ChecklistHandler, ConfigHandler, CreateHandler, ExportFormat, ExportHandler,
    InitHandler, MigrateDbHandler, MigrationHandler, PhaseHandler, ProjectHandler, SbomHandler,
    SearchHandler, SecurityHandler, StatusHandler, ToolHandler,
};

#[derive(Parser)]
#[command(name = "workspace")]
#[command(about = "Syntaxis")]
#[command(long_about = r#"Syntaxis - Orchestrate software syntaxis

CONFIGURATION SEARCH:
  Looks for config in order (uses first found):

  1. .project/lifecycle.toml  - If using Tools
  2. .vapora/lifecycle.toml         - If VAPORA project

  The tool automatically uses the first existing location.
  Example: If .project/ doesn't exist but .vapora/ does,
           it will use .vapora/lifecycle.toml automatically.

DIRECTORIES:
  .project/  - Tools installation (create if using Tools)
  .vapora/         - VAPORA platform configuration
  .coder/          - Documentation tracking & agent interaction
  .claude/         - Claude Code integration (skills, commands)

PHASES:
  creation → devel → update → review ↔ status → publish → archive
"#)]
struct Cli {
    #[arg(short, long, global = true)]
    verbose: bool,

    #[arg(
        short = 'p',
        long,
        global = true,
        help = "Project name (auto-detected if omitted)"
    )]
    project: Option<String>,

    #[arg(
        long,
        global = true,
        value_name = "PATH",
        help = "Configuration file path (overrides auto-discovery)"
    )]
    config: Option<String>,

    #[arg(long, global = true, help = "Use remote API instead of local database")]
    remote: bool,

    #[arg(
        long,
        global = true,
        value_name = "URL",
        help = "API server base URL (default: http://localhost:3000)"
    )]
    api_url: Option<String>,

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

#[derive(Subcommand)]
enum Commands {
    /// Initialize a new project
    Init {
        /// Project path
        path: Option<String>,
        /// Project type
        #[arg(short, long)]
        r#type: Option<String>,
    },
    /// Create project in database from TOML configuration
    Create,
    /// Migrate existing project to lifecycle management
    Migrate {
        /// Project path to migrate
        path: String,
        /// Skip backup creation
        #[arg(long)]
        no_backup: bool,
    },
    /// Show current phase
    Phase {
        #[command(subcommand)]
        subcommand: Option<PhaseCommands>,
    },
    /// Manage tools
    Tool {
        #[command(subcommand)]
        subcommand: Option<ToolCommands>,
    },
    /// Manage checklists
    Checklist {
        #[command(subcommand)]
        subcommand: Option<ChecklistCommands>,
    },
    /// Security management and assessment
    Security {
        #[command(subcommand)]
        subcommand: Option<SecurityCommands>,
    },
    /// Run compliance audit with vulnerability scanning
    Audit {
        /// Scan for vulnerabilities using cargo-audit
        #[arg(long)]
        audit_vulns: bool,
        /// Filter vulnerabilities against SBOM components (only show vulns affecting SBOM)
        #[arg(long)]
        sbom_filter: bool,
        /// Show detailed vulnerability analysis with remediation
        #[arg(long)]
        detailed: bool,
    },
    /// Show project status
    Status,
    /// Show configuration
    Config {
        #[command(subcommand)]
        subcommand: Option<ConfigCommands>,
    },
    /// Batch operations on multiple projects
    Batch {
        /// Batch operation file (TOML/JSON)
        file: String,
    },
    /// Search projects with advanced filters
    Search {
        /// Search query
        query: String,
        /// Filter by phase
        #[arg(long)]
        phase: Option<String>,
        /// Filter by type
        #[arg(long)]
        r#type: Option<String>,
        /// Sort by field
        #[arg(long, default_value = "name")]
        sort: String,
        /// Sort order (asc/desc)
        #[arg(long, default_value = "asc")]
        order: String,
    },
    /// Export project data
    Export {
        /// Export format (json, csv, toml, yaml, markdown) - uses config default if not specified
        #[arg(long)]
        format: Option<String>,
        /// Output file path - uses config default if not specified
        #[arg(long)]
        output: Option<String>,
        /// Project to export (optional, all if not specified)
        #[arg(long)]
        project: Option<String>,
    },
    /// Import project data
    Import {
        /// Import file path
        file: String,
        /// Import format (auto-detected if not specified)
        #[arg(long)]
        format: Option<String>,
        /// Overwrite existing projects
        #[arg(long)]
        overwrite: bool,
        /// Dry run (preview without importing)
        #[arg(long)]
        dry_run: bool,
    },
    /// Plugin management
    Plugin {
        #[command(subcommand)]
        subcommand: Option<PluginCommands>,
    },
    /// Generate Software Bill of Materials (SBOM) and dependency tree
    Sbom {
        #[command(subcommand)]
        subcommand: Option<SbomCommands>,
    },
    /// Manage projects
    Project {
        #[command(subcommand)]
        subcommand: Option<ProjectCommands>,
    },
    /// Migrate databases from local to global or run SQL migrations
    #[command(name = "migrate-db")]
    MigrateDb {
        /// Local database path to migrate (to global)
        #[arg(value_name = "PATH")]
        path: Option<String>,
        /// Scan for local databases instead of migrating
        #[arg(long)]
        scan: bool,
        /// Show migration status
        #[arg(long)]
        status: bool,
        /// Path to SQL migration file to execute
        #[arg(long, value_name = "FILE")]
        sql_file: Option<String>,
        /// Find and run all migration files in data/migration directory
        #[arg(long, value_name = "ROOT")]
        run_all: Option<String>,
    },
}

#[derive(Subcommand)]
enum PhaseCommands {
    /// Show current phase
    Current,
    /// Transition to new phase
    Transition {
        /// Target phase name
        phase: String,
        /// Check checklist before transitioning
        #[arg(long)]
        check_checklist: bool,
    },
}

#[derive(Subcommand)]
enum ToolCommands {
    /// List all tools
    List,
    /// Enable a tool
    Enable { tool: String },
    /// Disable a tool
    Disable { tool: String },
    /// Show tool status
    Status,
    /// List available Rust tool templates
    #[command(name = "list-rust")]
    ListRust,
    /// Add a Rust tool template to the project
    #[command(name = "add-rust-template")]
    AddRustTemplate { tool: String },
}

#[derive(Subcommand)]
enum ChecklistCommands {
    /// Show checklist
    Show { phase: Option<String> },
    /// Mark item complete
    Complete { item_id: String },
    /// Add item to checklist
    Add { description: String },
    /// Show available task types
    Types,
}

#[derive(Subcommand)]
enum ConfigCommands {
    /// Show configuration
    Show,
    /// Validate configuration
    Validate,
}

#[derive(Subcommand)]
enum PluginCommands {
    /// List installed plugins
    List,
    /// Install a plugin
    Install { path: String },
    /// Uninstall a plugin
    Uninstall { name: String },
    /// Enable a plugin
    Enable { name: String },
    /// Disable a plugin
    Disable { name: String },
    /// Show plugin info
    Info { name: String },
}

#[derive(Subcommand)]
enum SecurityCommands {
    /// Set security profile for the project
    Profile {
        /// Profile type (webapi, clitool, dataprocessing, iot, ml, opensourcelib, enterprise, desktop, mobile, microservice)
        profile_type: String,
    },
    /// Assess security posture
    Assess {
        /// Show detailed recommendations
        #[arg(long)]
        detailed: bool,
    },
}

#[derive(Subcommand)]
enum SbomCommands {
    /// Generate Software Bill of Materials in configured format(s)
    Generate,
    /// Generate and display dependency tree (cargo tree)
    Tree,
}

#[derive(Subcommand)]
enum ProjectCommands {
    /// List all projects in database
    List,
    /// Show details of a project
    Show {
        /// Project name
        name: String,
    },
    /// Detect current project from .project/lifecycle.toml
    Detect,
    /// Interactively select a project
    Select,
}

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

    // Set config path as environment variable for handlers (before loading config)
    if let Some(config_path) = &cli.config {
        std::env::set_var("SYNTAXIS_CONFIG_PATH", config_path);
    }

    // Load UI configuration after setting environment variable
    let _ui_config = if let Ok(Some(config_path)) =
        std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
            std::env::var("SYNTAXIS_CONFIG_PATH").ok()
        })) {
        ui_config::UiConfig::load_from_file(&config_path).ok()
    } else if let Some(config_path) = find_config_path_warn_conflicts("config.toml", None) {
        ui_config::UiConfig::load_from_file(config_path).ok()
    } else {
        None
    };

    // Setup logging
    if cli.verbose {
        tracing_subscriber::fmt::init();
    }

    // Note: Logo display is handled by the NuShell wrapper script based on
    // show_logo_on_empty config. The Rust binary runs after wrapper has already
    // determined whether to show the logo. This just loads config for consistency.

    // Initialize remote API client if --remote flag is set
    if cli.remote {
        let client = remote_ops::init_api_client(cli.api_url.clone())?;
        remote_ops::check_api_health(&client).await?;
    }

    match cli.command {
        Commands::Init { path, r#type } => {
            InitHandler::init(path.as_deref(), r#type.as_deref()).await?;
        }
        Commands::Create => {
            CreateHandler::create_project().await?;
        }
        Commands::Migrate { path, no_backup } => {
            MigrationHandler::migrate(&path, !no_backup).await?;
        }
        Commands::Phase { subcommand } => match subcommand {
            Some(PhaseCommands::Current) => PhaseHandler::show_current()?,
            Some(PhaseCommands::Transition {
                phase,
                check_checklist,
            }) => {
                PhaseHandler::transition_to(&phase, check_checklist)?;
            }
            None => {
                println!("Phase command requires a subcommand: current or transition");
                PhaseHandler::show_current()?;
            }
        },
        Commands::Tool { subcommand } => match subcommand {
            Some(ToolCommands::List) => ToolHandler::list_tools()?,
            Some(ToolCommands::Enable { tool }) => {
                ToolHandler::enable_tool(&tool)?;
            }
            Some(ToolCommands::Disable { tool }) => {
                ToolHandler::disable_tool(&tool)?;
            }
            Some(ToolCommands::Status) => ToolHandler::show_status()?,
            Some(ToolCommands::ListRust) => ToolHandler::list_rust_tools()?,
            Some(ToolCommands::AddRustTemplate { tool }) => {
                ToolHandler::add_rust_tool(&tool)?;
            }
            None => {
                println!("Tool command requires a subcommand");
                ToolHandler::list_tools()?;
            }
        },
        Commands::Checklist { subcommand } => match subcommand {
            Some(ChecklistCommands::Show { phase }) => {
                ChecklistHandler::show_checklist(phase.as_deref()).await?;
            }
            Some(ChecklistCommands::Complete { item_id }) => {
                ChecklistHandler::mark_complete(&item_id).await?;
            }
            Some(ChecklistCommands::Add { description }) => {
                ChecklistHandler::add_item(&description).await?;
            }
            Some(ChecklistCommands::Types) => {
                ChecklistHandler::show_types_help()?;
            }
            None => {
                ChecklistHandler::show_checklist(None).await?;
            }
        },
        Commands::Security { subcommand } => match subcommand {
            Some(SecurityCommands::Profile { profile_type }) => {
                SecurityHandler::set_security_profile(&profile_type)?;
            }
            Some(SecurityCommands::Assess { detailed }) => {
                SecurityHandler::assess_security(detailed)?;
            }
            None => println!("Security command requires a subcommand"),
        },
        Commands::Audit {
            audit_vulns,
            sbom_filter,
            detailed,
        } => {
            SecurityHandler::run_audit(audit_vulns, sbom_filter, detailed).await?;
        }
        Commands::Status => StatusHandler::show_status()?,
        Commands::Config { subcommand } => match subcommand {
            Some(ConfigCommands::Show) => ConfigHandler::show_config()?,
            Some(ConfigCommands::Validate) => ConfigHandler::validate_config()?,
            None => {
                println!("Config command requires a subcommand");
                ConfigHandler::show_config()?;
            }
        },
        Commands::Batch { file } => {
            let batch = BatchHandler::load_from_file(&file)?;
            let results = BatchHandler::execute(&batch)?;
            println!(
                "Batch operation completed: {} successful, {} failed",
                results.iter().filter(|r| r.success).count(),
                results.iter().filter(|r| !r.success).count()
            );
        }
        Commands::Search {
            query,
            phase,
            r#type,
            sort,
            order,
        } => {
            let mut filter = SearchHandler::parse_query(&query);
            if let Some(p) = phase {
                filter.phase = Some(p);
            }
            if let Some(t) = r#type {
                filter.project_type = Some(t);
            }
            filter.sort = sort;
            filter.order = order;

            println!(
                "Search filters: phase={:?}, type={:?}, query={:?}",
                filter.phase, filter.project_type, filter.query
            );
        }
        Commands::Export {
            format,
            output,
            project: _project,
        } => {
            // Parse format if provided
            let export_format = format
                .as_ref()
                .map(|f| ExportFormat::from_str(f))
                .transpose()?;

            // Find config file
            let config_path = find_config_path_warn_conflicts(
                "config.toml",
                cli.config.as_deref().map(std::path::Path::new),
            )
            .ok_or_else(|| {
                anyhow::anyhow!(
                    "Configuration not found. Please create:\n  \
                     - .syntaxis/config.toml (local), or\n  \
                     - .vapora/config.toml (local - takes precedence), or\n  \
                     - ~/.syntaxis/config.toml (global), or\n  \
                     - ~/.vapora/config.toml (global - takes precedence)\n\n  \
                     Or provide explicit path with --config PATH\n  \
                     Or run: syntaxis init"
                )
            })?;

            ExportHandler::execute_export(&config_path, export_format, output.as_deref(), None)
                .await?;
        }
        Commands::Import {
            file,
            format,
            overwrite,
            dry_run,
        } => {
            let import_format = if let Some(fmt) = format {
                handlers::ExportFormat::from_str(&fmt)?
            } else if file.ends_with(".json") {
                handlers::ExportFormat::Json
            } else if file.ends_with(".csv") {
                handlers::ExportFormat::Csv
            } else if file.ends_with(".toml") {
                handlers::ExportFormat::Toml
            } else {
                handlers::ExportFormat::Json
            };

            println!("Importing from {}", file);
            println!(
                "Format: {:?}, Overwrite: {}, Dry run: {}",
                import_format, overwrite, dry_run
            );
            println!(
                "Import configuration: source_file={}, format={:?}, overwrite={}, dry_run={}",
                file, import_format, overwrite, dry_run
            );
        }
        Commands::Plugin { subcommand } => match subcommand {
            Some(PluginCommands::List) => {
                println!("Plugin management not yet fully implemented");
            }
            Some(PluginCommands::Install { path }) => {
                println!("Installing plugin from: {}", path);
            }
            Some(PluginCommands::Uninstall { name }) => {
                println!("Uninstalling plugin: {}", name);
            }
            Some(PluginCommands::Enable { name }) => {
                println!("Enabling plugin: {}", name);
            }
            Some(PluginCommands::Disable { name }) => {
                println!("Disabling plugin: {}", name);
            }
            Some(PluginCommands::Info { name }) => {
                println!("Plugin info: {}", name);
            }
            None => {
                println!("Plugin command requires a subcommand");
            }
        },
        Commands::Sbom { subcommand } => match subcommand {
            Some(SbomCommands::Generate) => {
                SbomHandler::generate_sbom()?;
            }
            Some(SbomCommands::Tree) => {
                SbomHandler::generate_tree()?;
            }
            None => {
                println!("SBOM command requires a subcommand: generate or tree");
                SbomHandler::generate_sbom()?;
            }
        },
        Commands::Project { subcommand } => match subcommand {
            Some(ProjectCommands::List) => {
                ProjectHandler::list_projects().await?;
            }
            Some(ProjectCommands::Show { name }) => {
                ProjectHandler::show_project(&name).await?;
            }
            Some(ProjectCommands::Detect) => {
                ProjectHandler::detect_current()?;
            }
            Some(ProjectCommands::Select) => {
                let selected = ProjectHandler::select_from_list().await?;
                println!("\n✅ Selected project: {}", selected);
            }
            None => {
                println!("Project command requires a subcommand: list, show, detect, or select");
                ProjectHandler::list_projects().await?;
            }
        },
        Commands::MigrateDb {
            path,
            scan,
            status,
            sql_file,
            run_all,
        } => {
            if status {
                MigrateDbHandler::show_status().await?;
            } else if scan {
                let root = path.as_deref().unwrap_or(".");
                MigrateDbHandler::find_local_databases(root).await?;
            } else if let Some(db_path) = path {
                MigrateDbHandler::migrate_to_global(db_path.as_str()).await?;
            } else if let Some(sql_path) = sql_file {
                MigrateDbHandler::run_migration_file(&sql_path).await?;
            } else if let Some(root_path) = run_all {
                MigrateDbHandler::run_all_migrations(&root_path).await?;
            } else {
                println!("migrate-db requires one of: <PATH>, --scan, --status, --sql-file <FILE>, or --run-all <ROOT>");
                MigrateDbHandler::show_status().await?;
            }
        }
    }

    Ok(())
}
