//! Rustelo CLI - Template-based Project Management Tool
//!
//! This CLI tool helps developers:
//! - Create new projects from templates
//! - Clone and customize foundation crates locally
//! - Migrate existing projects to trait-based architecture
//! - Manage local trait implementations

use anyhow::{Context, Result};
use clap::{Parser, Subcommand};
use console::style;
use dialoguer::{theme::ColorfulTheme, Confirm, Input, MultiSelect, Select};
use handlebars::Handlebars;
use indicatif::{ProgressBar, ProgressStyle};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::fs;
use std::path::{Path, PathBuf};
use walkdir::WalkDir;

#[derive(Parser)]
#[command(
    name = "rustelo",
    about = "Rustelo Framework CLI - Template-based project management",
    version = "0.1.0"
)]
struct Cli {
    #[command(subcommand)]
    command: Commands,
}

#[derive(Subcommand)]
enum Commands {
    /// Create a new project from templates
    New {
        /// Project name
        name: String,
        /// Template type (basic, cms, minimal, enterprise, saas, ai-powered, ecommerce)
        #[arg(short, long)]
        template: Option<String>,
        /// Features to include
        #[arg(short, long, action = clap::ArgAction::Append)]
        features: Vec<String>,
        /// Project directory (defaults to name)
        #[arg(short, long)]
        path: Option<PathBuf>,
        /// Skip interactive setup
        #[arg(short, long)]
        quiet: bool,
    },
    /// Clone foundation crates for local customization
    Clone {
        /// Crate to clone (core-lib, client, server, or all)
        crate_name: String,
        /// Target directory
        #[arg(short, long)]
        target: Option<PathBuf>,
    },
    /// Add feature to existing project
    Add {
        /// Feature name (analytics, smart-build, debugging-tools, etc.)
        feature: String,
        /// Project directory
        #[arg(short, long)]
        path: Option<PathBuf>,
    },
    /// Remove feature from existing project
    Remove {
        /// Feature name
        feature: String,
        /// Project directory
        #[arg(short, long)]
        path: Option<PathBuf>,
        /// Force removal without confirmation
        #[arg(short, long)]
        force: bool,
    },
    /// Update framework while preserving customizations
    Update {
        /// Project directory
        #[arg(short, long)]
        path: Option<PathBuf>,
        /// Sync templates from remote
        #[arg(long)]
        sync_templates: bool,
    },
    /// Sync templates from main repository
    Sync {
        /// What to sync (templates, project-templates, crate-templates, feature-templates)
        target: String,
        /// Project directory
        #[arg(short, long)]
        path: Option<PathBuf>,
    },
    /// Initialize trait-based architecture in existing project
    Init {
        /// Project directory
        #[arg(short, long)]
        path: Option<PathBuf>,
        /// Skip backup creation
        #[arg(long)]
        no_backup: bool,
    },
    /// Migrate existing project to new architecture
    Migrate {
        /// Project directory
        #[arg(short, long)]
        path: Option<PathBuf>,
        /// Force migration without confirmation
        #[arg(short, long)]
        force: bool,
    },
    /// Check project architecture status
    Status {
        /// Project directory
        #[arg(short, long)]
        path: Option<PathBuf>,
    },
    /// Create local override for configuration or component
    Override {
        /// Type of override (config, component, page)
        override_type: String,
        /// Name of item to override
        name: String,
        /// Project directory
        #[arg(short, long)]
        path: Option<PathBuf>,
    },
    /// List all active overrides
    ListOverrides {
        /// Project directory
        #[arg(short, long)]
        path: Option<PathBuf>,
    },
    /// Trace how a configuration or component is resolved
    Trace {
        /// Type to trace (config, component, page)
        trace_type: String,
        /// Name of item to trace
        name: String,
        /// Project directory
        #[arg(short, long)]
        path: Option<PathBuf>,
    },
    /// Remove local override
    RemoveOverride {
        /// Type of override (config, component, page)
        override_type: String,
        /// Name of item to remove override for
        name: String,
        /// Project directory
        #[arg(short, long)]
        path: Option<PathBuf>,
        /// Force removal without confirmation
        #[arg(short, long)]
        force: bool,
    },
}

#[derive(Debug, Serialize, Deserialize)]
struct ProjectConfig {
    name: String,
    template_type: TemplateType,
    features: Vec<String>,
    traits_customized: Vec<String>,
    architecture_version: String,
}

#[derive(Debug, Serialize, Deserialize)]
enum TemplateType {
    Minimal,
    Standard,
    Full,
    Custom,
}

#[derive(Debug, Serialize, Deserialize)]
struct TemplateContext {
    project_name: String,
    project_name_snake: String,
    project_name_kebab: String,
    features: Vec<String>,
    has_auth: bool,
    has_content: bool,
    has_localization: bool,
    architecture_version: String,
}

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

    match cli.command {
        Commands::New { name, template, features, path, quiet } => {
            create_new_project(&name, template, features, path, quiet).await?;
        }
        Commands::Clone { crate_name, target } => {
            clone_foundation_crate(&crate_name, target).await?;
        }
        Commands::Add { feature, path } => {
            add_feature_to_project(&feature, path).await?;
        }
        Commands::Remove { feature, path, force } => {
            remove_feature_from_project(&feature, path, force).await?;
        }
        Commands::Update { path, sync_templates } => {
            update_project_framework(path, sync_templates).await?;
        }
        Commands::Sync { target, path } => {
            sync_templates(&target, path).await?;
        }
        Commands::Init { path, no_backup } => {
            initialize_trait_architecture(path, !no_backup).await?;
        }
        Commands::Migrate { path, force } => {
            migrate_to_new_architecture(path, force).await?;
        }
        Commands::Status { path } => {
            check_project_status(path).await?;
        }
        Commands::Override { override_type, name, path } => {
            create_local_override(&override_type, &name, path).await?;
        }
        Commands::ListOverrides { path } => {
            list_active_overrides(path).await?;
        }
        Commands::Trace { trace_type, name, path } => {
            trace_resolution(&trace_type, &name, path).await?;
        }
        Commands::RemoveOverride { override_type, name, path, force } => {
            remove_local_override(&override_type, &name, path, force).await?;
        }
    }

    Ok(())
}

async fn create_new_project(name: &str, template: Option<String>, features: Vec<String>, path: Option<PathBuf>, quiet: bool) -> Result<()> {
    println!("{}", style("🚀 Creating new Rustelo project").bold().green());

    let project_path = path.unwrap_or_else(|| PathBuf::from(name));

    if project_path.exists() {
        if !Confirm::with_theme(&ColorfulTheme::default())
            .with_prompt("Directory already exists. Continue?")
            .default(false)
            .interact()?
        {
            return Ok(());
        }
    }

    // Use unified template system
    let selected_template = if let Some(template_name) = template {
        template_name
    } else if quiet {
        "basic".to_string()
    } else {
        let available_templates = vec![
            "basic", "cms", "minimal", "enterprise",
            "saas", "ai-powered", "ecommerce"
        ];
        let descriptions = vec![
            "Basic - Standard web application template",
            "CMS - Content management focused template",
            "Minimal - Lightweight template for prototypes",
            "Enterprise - Advanced features for large deployments",
            "SaaS - Software-as-a-Service template",
            "AI-Powered - AI/ML integration template",
            "E-Commerce - Online store functionality template",
        ];

        let selection = Select::with_theme(&ColorfulTheme::default())
            .with_prompt("Choose project template")
            .items(&descriptions)
            .default(0)
            .interact()?;

        available_templates[selection].to_string()
    };

    let selected_features = if !features.is_empty() {
        features
    } else if quiet {
        vec!["content-static".to_string()]
    } else {
        select_unified_features(&selected_template)?
    };

    let context = create_template_context(name, &selected_features)?;

    create_unified_project_structure(&project_path, &selected_template, &context).await?;

    println!("{}", style("✅ Project created successfully!").bold().green());
    println!("\nNext steps:");
    println!("  cd {}", project_path.display());
    println!("  cargo leptos watch");

    Ok(())
}

async fn clone_foundation_crate(crate_name: &str, target: Option<PathBuf>) -> Result<()> {
    println!("{} {}",
        style("📋 Cloning foundation crate:").bold().blue(),
        style(crate_name).yellow()
    );

    let templates_dir = find_templates_directory()?;
    let crates_to_clone = match crate_name {
        "all" => vec!["core-lib-template", "client-template", "server-template"],
        "core-lib" => vec!["core-lib-template"],
        "client" => vec!["client-template"],
        "server" => vec!["server-template"],
        _ => {
            eprintln!("❌ Unknown crate: {}. Available: core-lib, client, server, all", crate_name);
            return Ok(());
        }
    };

    let target_dir = target.unwrap_or_else(|| PathBuf::from("local-crates"));
    fs::create_dir_all(&target_dir)?;

    for template_name in crates_to_clone {
        let source = templates_dir.join(template_name);
        let dest_name = template_name.replace("-template", "");
        let dest = target_dir.join(&dest_name);

        if !source.exists() {
            eprintln!("⚠️  Template not found: {}", source.display());
            continue;
        }

        copy_directory(&source, &dest)?;
        customize_cloned_crate(&dest, &dest_name)?;

        println!("✅ Cloned {} → {}", template_name, dest.display());
    }

    println!("\n{}", style("🎯 Customization Guide:").bold().cyan());
    println!("1. Edit src/traits_impl.rs to customize trait implementations");
    println!("2. Modify Cargo.toml dependencies as needed");
    println!("3. Update your main project to use local crates:");
    println!("   [dependencies.core-lib]");
    println!("   path = \"local-crates/core-lib\"");

    Ok(())
}

async fn initialize_trait_architecture(path: Option<PathBuf>, should_create_backup: bool) -> Result<()> {
    let project_path = path.unwrap_or_else(|| PathBuf::from("."));

    println!("{}", style("🔧 Initializing trait-based architecture").bold().blue());

    if should_create_backup {
        create_backup(&project_path).await?;
    }

    // Add trait dependencies to existing Cargo.toml files
    update_cargo_toml_for_traits(&project_path).await?;

    // Create basic traits_impl.rs if it doesn't exist
    create_traits_implementation(&project_path).await?;

    // Update routing files to use trait-based approach
    update_routing_files(&project_path).await?;

    println!("✅ Trait-based architecture initialized!");
    println!("\nNext steps:");
    println!("1. Review generated traits_impl.rs files");
    println!("2. Customize trait implementations as needed");
    println!("3. Test with: cargo leptos watch");

    Ok(())
}

async fn migrate_to_new_architecture(path: Option<PathBuf>, force: bool) -> Result<()> {
    let project_path = path.unwrap_or_else(|| PathBuf::from("."));

    println!("{}", style("🔄 Migrating to new trait-based architecture").bold().yellow());

    let status = analyze_project_status(&project_path).await?;

    if !force {
        println!("\nCurrent project status:");
        print_project_status(&status);

        if !Confirm::with_theme(&ColorfulTheme::default())
            .with_prompt("Proceed with migration?")
            .default(false)
            .interact()?
        {
            return Ok(());
        }
    }

    let pb = ProgressBar::new(5);
    pb.set_style(ProgressStyle::default_bar()
        .template("{spinner:.green} [{elapsed_precise}] [{bar:40.cyan/blue}] {pos:>7}/{len:7} {msg}")?);

    pb.set_message("Creating backup...");
    create_backup(&project_path).await?;
    pb.inc(1);

    pb.set_message("Updating dependencies...");
    update_cargo_toml_for_traits(&project_path).await?;
    pb.inc(1);

    pb.set_message("Creating trait implementations...");
    create_traits_implementation(&project_path).await?;
    pb.inc(1);

    pb.set_message("Updating routing code...");
    update_routing_files(&project_path).await?;
    pb.inc(1);

    pb.set_message("Finalizing migration...");
    create_migration_summary(&project_path).await?;
    pb.inc(1);

    pb.finish_with_message("Migration completed!");

    println!("\n{}", style("✅ Migration successful!").bold().green());
    println!("\nMigration summary saved to: MIGRATION_SUMMARY.md");

    Ok(())
}

async fn check_project_status(path: Option<PathBuf>) -> Result<()> {
    let project_path = path.unwrap_or_else(|| PathBuf::from("."));

    let status = analyze_project_status(&project_path).await?;
    print_project_status(&status);

    Ok(())
}

fn select_features(template_type: &TemplateType) -> Result<Vec<String>> {
    let available_features = vec![
        "routing", "localization", "auth", "content-static",
        "content-db", "email", "tls", "metrics"
    ];

    let defaults = match template_type {
        TemplateType::Minimal => vec![0], // routing only
        TemplateType::Standard => vec![0, 1], // routing + localization
        TemplateType::Full => vec![0, 1, 2, 3, 4, 5], // most features
        TemplateType::Custom => vec![], // user selects
    };

    let selections = MultiSelect::with_theme(&ColorfulTheme::default())
        .with_prompt("Select features")
        .items(&available_features)
        .defaults(&defaults.iter().map(|&i| i < available_features.len()).collect::<Vec<_>>())
        .interact()?;

    Ok(selections.into_iter()
        .map(|i| available_features[i].to_string())
        .collect())
}

fn create_template_context(name: &str, features: &[String]) -> Result<TemplateContext> {
    Ok(TemplateContext {
        project_name: name.to_string(),
        project_name_snake: name.replace('-', "_"),
        project_name_kebab: name.replace('_', "-"),
        features: features.to_vec(),
        has_auth: features.contains(&"auth".to_string()),
        has_content: features.iter().any(|f| f.starts_with("content")),
        has_localization: features.contains(&"localization".to_string()),
        architecture_version: "1.0.0".to_string(),
    })
}

async fn create_project_structure(
    path: &Path,
    template_type: &TemplateType,
    context: &TemplateContext,
) -> Result<()> {
    let templates_dir = find_templates_directory()?;

    // Copy base template
    let base_template = match template_type {
        TemplateType::Minimal => "minimal-project",
        _ => "standard-project",
    };

    // For now, copy from core-lib-template as a base
    let source = templates_dir.join("core-lib-template");
    if source.exists() {
        copy_directory(&source, path)?;
        process_templates(path, context)?;
    } else {
        // Create minimal project structure
        create_minimal_project_structure(path, context).await?;
    }

    Ok(())
}

async fn create_minimal_project_structure(path: &Path, context: &TemplateContext) -> Result<()> {
    fs::create_dir_all(path)?;

    // Create basic Cargo.toml
    let cargo_toml = format!(r#"[package]
name = "{}"
version = "0.1.0"
edition = "2021"

[dependencies]
# Pure trait dependencies for new architecture
rustelo-routing-traits = {{ path = "../traits/routing-traits" }}
rustelo-component-traits = {{ path = "../traits/component-traits" }}
rustelo-core-types = {{ path = "../traits/core-types" }}

[lib]
name = "{}"
path = "src/lib.rs"
"#, context.project_name_kebab, context.project_name_snake);

    fs::write(path.join("Cargo.toml"), cargo_toml)?;

    // Create src/lib.rs with trait implementations
    let lib_rs = r#"//! Local trait implementations for this project
//!
//! This module provides customized implementations of the pure traits
//! from the rustelo-*-traits crates, allowing full local customization
//! without depending on foundation crates.

use rustelo_routing_traits::*;
use rustelo_component_traits::*;
use rustelo_core_types::*;
use std::collections::HashMap;

pub mod traits_impl;

pub use traits_impl::*;
"#;

    fs::create_dir_all(path.join("src"))?;
    fs::write(path.join("src/lib.rs"), lib_rs)?;

    Ok(())
}

fn find_templates_directory() -> Result<PathBuf> {
    // Try to find templates directory relative to current location
    let current = std::env::current_dir()?;

    // Look for templates in common locations
    let candidates = vec![
        current.join("crates/templates"),
        current.join("../crates/templates"),
        current.join("../../crates/templates"),
        current.join("templates"),
    ];

    for candidate in candidates {
        if candidate.exists() && candidate.is_dir() {
            return Ok(candidate);
        }
    }

    Err(anyhow::anyhow!("Templates directory not found. Make sure you're running from within a Rustelo project."))
}

fn copy_directory(src: &Path, dst: &Path) -> Result<()> {
    fs::create_dir_all(dst)?;

    for entry in WalkDir::new(src) {
        let entry = entry?;
        let path = entry.path();
        let relative_path = path.strip_prefix(src)?;
        let dst_path = dst.join(relative_path);

        if path.is_dir() {
            fs::create_dir_all(&dst_path)?;
        } else {
            if let Some(parent) = dst_path.parent() {
                fs::create_dir_all(parent)?;
            }
            fs::copy(path, &dst_path)?;
        }
    }

    Ok(())
}

fn customize_cloned_crate(crate_path: &Path, crate_name: &str) -> Result<()> {
    // Update Cargo.toml to use local trait dependencies
    let cargo_toml_path = crate_path.join("Cargo.toml");
    if cargo_toml_path.exists() {
        let mut content = fs::read_to_string(&cargo_toml_path)?;

        // Replace template name with actual crate name
        content = content.replace("-template", "");
        content = content.replace("Template", &capitalize(crate_name));

        // Update trait dependency paths to be relative to local setup
        content = content.replace(
            "path = \"../../../traits/",
            "path = \"../../traits/"
        );

        fs::write(&cargo_toml_path, content)?;
    }

    // Add customization comment to traits_impl.rs
    let traits_impl_path = crate_path.join("src/traits_impl.rs");
    if traits_impl_path.exists() {
        let mut content = fs::read_to_string(&traits_impl_path)?;
        let header = format!(
            "//! Local trait implementations for {}\n//!\n//! This file was generated by `rustelo clone {}` and can be customized freely.\n//! Modify these implementations to suit your project's specific needs.\n\n",
            crate_name, crate_name
        );
        content = header + &content;
        fs::write(&traits_impl_path, content)?;
    }

    Ok(())
}

fn process_templates(path: &Path, context: &TemplateContext) -> Result<()> {
    let mut handlebars = Handlebars::new();

    for entry in WalkDir::new(path) {
        let entry = entry?;
        let file_path = entry.path();

        if file_path.is_file() {
            if let Some(extension) = file_path.extension() {
                if extension == "toml" || extension == "rs" || extension == "md" {
                    let content = fs::read_to_string(file_path)?;
                    let processed = handlebars.render_template(&content, context)?;
                    fs::write(file_path, processed)?;
                }
            }
        }
    }

    Ok(())
}

async fn create_backup(project_path: &Path) -> Result<()> {
    let backup_path = project_path.join(".backup-pre-migration");

    if backup_path.exists() {
        fs::remove_dir_all(&backup_path)?;
    }

    // Backup critical files
    let files_to_backup = vec![
        "Cargo.toml",
        "src/lib.rs",
        "crates/client/src/routing.rs",
        "crates/server/src/routing.rs",
        "crates/core-lib/build.rs",
    ];

    for file in files_to_backup {
        let src = project_path.join(file);
        if src.exists() {
            let dst = backup_path.join(file);
            if let Some(parent) = dst.parent() {
                fs::create_dir_all(parent)?;
            }
            fs::copy(&src, &dst)?;
        }
    }

    println!("📦 Backup created at: {}", backup_path.display());
    Ok(())
}

async fn update_cargo_toml_for_traits(project_path: &Path) -> Result<()> {
    // This would update Cargo.toml files to add trait dependencies
    // Implementation would be more complex in practice
    println!("🔧 Updated Cargo.toml files for trait dependencies");
    Ok(())
}

async fn create_traits_implementation(project_path: &Path) -> Result<()> {
    // This would create traits_impl.rs files
    // Implementation would be more complex in practice
    println!("📝 Created trait implementation files");
    Ok(())
}

async fn update_routing_files(project_path: &Path) -> Result<()> {
    // This would update routing files to use trait-based approach
    // Implementation would be more complex in practice
    println!("🔄 Updated routing files for trait-based architecture");
    Ok(())
}

async fn create_migration_summary(project_path: &Path) -> Result<()> {
    let summary = r#"# Migration Summary

## What Was Changed

1. **Dependencies Updated**: Added trait crate dependencies
2. **Code Generation Removed**: Replaced with trait-based runtime resolution
3. **Trait Implementations Created**: Added local trait implementations
4. **Routing Updated**: Client and server routing now use traits

## Next Steps

1. Review `src/traits_impl.rs` files
2. Customize trait implementations as needed
3. Test the application: `cargo leptos watch`
4. Remove old generated code once satisfied

## Rollback

To rollback, restore from `.backup-pre-migration/` directory.
"#;

    fs::write(project_path.join("MIGRATION_SUMMARY.md"), summary)?;
    Ok(())
}

#[derive(Debug)]
struct ProjectStatus {
    has_trait_deps: bool,
    has_traits_impl: bool,
    has_old_generation: bool,
    architecture_version: String,
}

async fn analyze_project_status(project_path: &Path) -> Result<ProjectStatus> {
    let cargo_toml = project_path.join("Cargo.toml");
    let has_trait_deps = if cargo_toml.exists() {
        let content = fs::read_to_string(&cargo_toml)?;
        content.contains("rustelo-routing-traits")
    } else {
        false
    };

    let traits_impl = project_path.join("src/traits_impl.rs");
    let has_traits_impl = traits_impl.exists();

    let build_rs = project_path.join("crates/core-lib/build.rs");
    let has_old_generation = if build_rs.exists() {
        let content = fs::read_to_string(&build_rs)?;
        content.contains("generate_shared_resources")
    } else {
        false
    };

    Ok(ProjectStatus {
        has_trait_deps,
        has_traits_impl,
        has_old_generation,
        architecture_version: "1.0.0".to_string(),
    })
}

fn print_project_status(status: &ProjectStatus) {
    println!("{}", style("📊 Project Architecture Status").bold().cyan());
    println!();

    let check = |condition: bool| if condition { "✅" } else { "❌" };

    println!("{} Trait dependencies: {}",
        check(status.has_trait_deps),
        if status.has_trait_deps { "Present" } else { "Missing" }
    );

    println!("{} Trait implementations: {}",
        check(status.has_traits_impl),
        if status.has_traits_impl { "Present" } else { "Missing" }
    );

    println!("{} Legacy code generation: {}",
        if status.has_old_generation { "⚠️" } else { "✅" },
        if status.has_old_generation { "Still present" } else { "Removed" }
    );

    println!();
    println!("Architecture version: {}", style(&status.architecture_version).yellow());
}

fn capitalize(s: &str) -> String {
    let mut chars = s.chars();
    match chars.next() {
        None => String::new(),
        Some(first) => first.to_uppercase().chain(chars).collect(),
    }
}

// === New Unified Template System Functions ===

/// Select features for unified template system
fn select_unified_features(template: &str) -> Result<Vec<String>> {
    let available_features = vec![
        "content-static", "content-db", "auth", "email",
        "tls", "metrics", "analytics", "smart-build", "debugging-tools"
    ];

    let defaults = match template {
        "minimal" => vec![0], // content-static only
        "basic" => vec![0], // content-static
        "cms" => vec![0, 1, 2], // content-static, content-db, auth
        "enterprise" => vec![0, 1, 2, 3, 4, 5], // most features
        "saas" => vec![0, 1, 2, 3, 4, 5, 6], // includes analytics
        "ai-powered" => vec![0, 2, 4, 5, 6], // content, auth, tls, metrics, analytics
        "ecommerce" => vec![0, 1, 2, 3, 4, 5], // content, auth, email, tls, metrics
        _ => vec![0], // default to content-static
    };

    let selections = MultiSelect::with_theme(&ColorfulTheme::default())
        .with_prompt("Select features")
        .items(&available_features)
        .defaults(&defaults.iter().map(|&i| i < available_features.len()).collect::<Vec<_>>())
        .interact()?;

    Ok(selections.into_iter()
        .map(|i| available_features[i].to_string())
        .collect())
}

/// Create project structure using unified template system
async fn create_unified_project_structure(
    path: &Path,
    template: &str,
    context: &TemplateContext,
) -> Result<()> {
    let templates_dir = find_unified_templates_directory()?;
    let project_template_path = templates_dir.join("project").join(template);

    if project_template_path.exists() {
        copy_directory(&project_template_path, path)?;
        process_templates(path, context)?;

        // Apply feature templates
        apply_feature_templates(path, &context.features).await?;
    } else {
        println!("⚠️ Template '{}' not found, creating minimal project", template);
        create_minimal_project_structure(path, context).await?;
    }

    Ok(())
}

/// Find unified templates directory
fn find_unified_templates_directory() -> Result<PathBuf> {
    let current = std::env::current_dir()?;

    // Look for unified template structure
    let candidates = vec![
        current.join("rustelo-templates"),
        current.join("../rustelo-templates"),
        current.join("../../rustelo-templates"),
        current.join("templates"), // fallback to old structure
        current.join("../templates"),
        current.join("../../templates"),
    ];

    for candidate in candidates {
        if candidate.exists() && candidate.is_dir() {
            return Ok(candidate);
        }
    }

    Err(anyhow::anyhow!("Unified templates directory not found. Run 'cargo rustelo sync templates' to download templates."))
}

/// Apply feature templates to project
async fn apply_feature_templates(project_path: &Path, features: &[String]) -> Result<()> {
    let templates_dir = find_unified_templates_directory()?;
    let features_dir = templates_dir.join("features");

    for feature in features {
        let feature_template = features_dir.join(feature);
        if feature_template.exists() {
            println!("  🎛️ Applying {} feature template", feature);
            copy_feature_template(&feature_template, project_path, feature)?;
        } else {
            println!("  ⚠️ Feature template not found: {}", feature);
        }
    }

    Ok(())
}

/// Copy feature template to project
fn copy_feature_template(feature_path: &Path, project_path: &Path, feature_name: &str) -> Result<()> {
    for entry in WalkDir::new(feature_path) {
        let entry = entry?;
        let source_path = entry.path();
        let relative_path = source_path.strip_prefix(feature_path)?;
        let dest_path = project_path.join(relative_path);

        if source_path.is_dir() {
            fs::create_dir_all(&dest_path)?;
        } else if source_path.is_file() {
            if let Some(parent) = dest_path.parent() {
                fs::create_dir_all(parent)?;
            }

            // Handle configuration merging for certain file types
            if let Some(filename) = dest_path.file_name() {
                if filename == "Cargo.toml" {
                    merge_cargo_toml(&dest_path, source_path, feature_name)?;
                } else if filename == "justfile" {
                    merge_justfile(&dest_path, source_path, feature_name)?;
                } else {
                    fs::copy(source_path, &dest_path)?;
                }
            }
        }
    }

    Ok(())
}

/// Merge feature Cargo.toml with project Cargo.toml
fn merge_cargo_toml(project_toml: &Path, feature_toml: &Path, feature_name: &str) -> Result<()> {
    if project_toml.exists() {
        // Read both files and merge dependencies
        let mut project_content = fs::read_to_string(project_toml)?;
        let feature_content = fs::read_to_string(feature_toml)?;

        // Simple merge - append feature dependencies
        project_content.push_str(&format!("\n# {} feature dependencies\n", feature_name));
        project_content.push_str(&feature_content);

        fs::write(project_toml, project_content)?;
    } else {
        fs::copy(feature_toml, project_toml)?;
    }

    Ok(())
}

/// Merge feature justfile with project justfile
fn merge_justfile(project_justfile: &Path, feature_justfile: &Path, feature_name: &str) -> Result<()> {
    if project_justfile.exists() {
        let mut project_content = fs::read_to_string(project_justfile)?;
        let feature_content = fs::read_to_string(feature_justfile)?;

        project_content.push_str(&format!("\n# {} feature commands\n", feature_name));
        project_content.push_str(&feature_content);

        fs::write(project_justfile, project_content)?;
    } else {
        fs::copy(feature_justfile, project_justfile)?;
    }

    Ok(())
}

/// Add feature to existing project
async fn add_feature_to_project(feature: &str, path: Option<PathBuf>) -> Result<()> {
    let project_path = path.unwrap_or_else(|| PathBuf::from("."));

    println!("{} {}",
        style("🎛️ Adding feature:").bold().green(),
        style(feature).yellow()
    );

    // Apply feature template
    apply_feature_templates(&project_path, &[feature.to_string()]).await?;

    // Update project configuration
    update_project_config_for_feature(&project_path, feature, true).await?;

    println!("✅ Feature '{}' added successfully!", feature);
    println!("💡 Run 'cargo leptos watch' to test the changes");

    Ok(())
}

/// Remove feature from existing project
async fn remove_feature_from_project(feature: &str, path: Option<PathBuf>, force: bool) -> Result<()> {
    let project_path = path.unwrap_or_else(|| PathBuf::from("."));

    println!("{} {}",
        style("🗑️ Removing feature:").bold().yellow(),
        style(feature).red()
    );

    if !force {
        if !Confirm::with_theme(&ColorfulTheme::default())
            .with_prompt(&format!("Remove feature '{}'? This may break functionality.", feature))
            .default(false)
            .interact()?
        {
            return Ok(());
        }
    }

    // Update project configuration
    update_project_config_for_feature(&project_path, feature, false).await?;

    // Note: We don't remove files as they might have been customized
    println!("✅ Feature '{}' removed from configuration", feature);
    println!("💡 Feature files remain - remove manually if desired");

    Ok(())
}

/// Update framework while preserving customizations
async fn update_project_framework(path: Option<PathBuf>, sync_templates: bool) -> Result<()> {
    let project_path = path.unwrap_or_else(|| PathBuf::from("."));

    println!("{}", style("🔄 Updating Rustelo framework").bold().blue());

    if sync_templates {
        println!("📋 Syncing templates from repository...");
        sync_templates("templates", Some(project_path.clone())).await?;
    }

    // Create backup before update
    create_backup(&project_path).await?;

    // Update framework dependencies in Cargo.toml
    update_framework_dependencies(&project_path).await?;

    // Validate that customizations are preserved
    validate_customizations_preserved(&project_path).await?;

    println!("✅ Framework updated successfully!");
    println!("💡 Your customizations have been preserved");

    Ok(())
}

/// Sync templates from main repository
async fn sync_templates(target: &str, path: Option<PathBuf>) -> Result<()> {
    let _project_path = path.unwrap_or_else(|| PathBuf::from("."));

    println!("{} {}",
        style("🔄 Syncing templates:").bold().blue(),
        style(target).yellow()
    );

    match target {
        "templates" => {
            println!("  📄 Syncing all template types...");
            // Implementation would sync from main repository
            println!("  ✅ All templates synced");
        }
        "project-templates" => {
            println!("  📄 Syncing project templates...");
            println!("  ✅ Project templates synced");
        }
        "crate-templates" => {
            println!("  🔧 Syncing crate templates...");
            println!("  ✅ Crate templates synced");
        }
        "feature-templates" => {
            println!("  🎛️ Syncing feature templates...");
            println!("  ✅ Feature templates synced");
        }
        _ => {
            println!("⚠️ Unknown sync target: {}", target);
            println!("📋 Available targets: templates, project-templates, crate-templates, feature-templates");
        }
    }

    println!("💡 Note: Remote sync not yet implemented. Using local templates.");

    Ok(())
}

/// Update project configuration for feature
async fn update_project_config_for_feature(project_path: &Path, feature: &str, add: bool) -> Result<()> {
    let config_path = project_path.join("rustelo.toml");

    // Create or update rustelo.toml with feature configuration
    let config_content = if config_path.exists() {
        fs::read_to_string(&config_path)?
    } else {
        String::new()
    };

    let updated_content = if add {
        format!("{}\n[features]\n{} = true\n", config_content, feature)
    } else {
        config_content.replace(&format!("{} = true", feature), &format!("# {} = false", feature))
    };

    fs::write(&config_path, updated_content)?;

    Ok(())
}

/// Update framework dependencies
async fn update_framework_dependencies(project_path: &Path) -> Result<()> {
    println!("  🔧 Updating framework dependencies...");

    // Update workspace Cargo.toml if it exists
    let workspace_cargo = project_path.join("Cargo.toml");
    if workspace_cargo.exists() {
        // Implementation would update rustelo dependencies to latest versions
        println!("  ✅ Framework dependencies updated");
    }

    Ok(())
}

/// Validate that customizations are preserved
async fn validate_customizations_preserved(project_path: &Path) -> Result<()> {
    println!("  🔍 Validating customizations are preserved...");

    // Check for local-crates directory
    let local_crates = project_path.join("local-crates");
    if local_crates.exists() {
        println!("  ✅ Local crate customizations preserved");
    }

    // Check for custom configurations
    let rustelo_config = project_path.join("rustelo.toml");
    if rustelo_config.exists() {
        println!("  ✅ Project configuration preserved");
    }

    println!("  ✅ All customizations validated");

    Ok(())
}

// === Layered Override System CLI Commands ===

/// Create a local override for configuration or component
async fn create_local_override(override_type: &str, name: &str, path: Option<PathBuf>) -> Result<()> {
    let project_path = path.unwrap_or_else(|| PathBuf::from("."));

    println!("{} {} '{}'",
        style("🎛️ Creating local override for:").bold().green(),
        override_type,
        style(name).yellow()
    );

    match override_type {
        "config" => create_config_override(&project_path, name).await?,
        "component" => create_component_override(&project_path, name).await?,
        "page" => create_page_override(&project_path, name).await?,
        _ => {
            println!("⚠️ Unknown override type: {}", override_type);
            println!("📋 Available types: config, component, page");
            return Ok(());
        }
    }

    println!("✅ Local override created successfully!");
    println!("💡 Edit the file to customize behavior");

    Ok(())
}

/// Create a configuration override
async fn create_config_override(project_path: &Path, config_name: &str) -> Result<()> {
    let local_config_dir = project_path.join("config/local");
    fs::create_dir_all(&local_config_dir)?;

    let config_path = local_config_dir.join(config_name);

    if config_path.exists() {
        println!("⚠️ Local override already exists: {}", config_path.display());
        return Ok(());
    }

    // Create a basic config template based on the config name
    let template_content = match config_name {
        "rustelo.toml" => r#"# Local Rustelo configuration override
# This file has the highest precedence in the layered override system

[project]
# name = "your-project-name"
# version = "1.0.0"

[features]
# analytics = { enabled = true, config = { level = "detailed" } }

[dev]
# hot_reload = true
# debug_mode = true
# log_level = "debug"

[build]
# optimize = true
# target = "wasm32-unknown-unknown"
"#,
        "package.json" => r#"{
  "// comment": "Local package.json override - highest precedence",
  "scripts": {
    "// example": "Custom scripts go here"
  },
  "dependencies": {
    "// example": "Custom dependencies go here"
  },
  "devDependencies": {
    "// example": "Custom dev dependencies go here"
  }
}
"#,
        "uno.config.ts" => r#"// Local UnoCSS configuration override
export default {
  theme: {
    colors: {
      // Local color overrides
      // primary: '#ef4444',
    },
    fonts: {
      // Local font overrides
      // sans: ['Inter', 'sans-serif'],
    }
  },
  shortcuts: {
    // Local shortcuts
    // 'custom-btn': 'px-4 py-2 rounded bg-primary text-white hover:bg-primary/80',
  },
  safelist: [
    // Classes that should always be included
  ]
}
"#,
        _ => {
            format!(r#"# Local override for {}
# This file has the highest precedence in the layered override system
# Edit this file to customize the configuration

"#, config_name)
        }
    };

    fs::write(&config_path, template_content)?;
    println!("  📝 Created: {}", config_path.display());

    Ok(())
}

/// Create a component override
async fn create_component_override(project_path: &Path, component_name: &str) -> Result<()> {
    let local_components_dir = project_path.join("src/components/local");
    fs::create_dir_all(&local_components_dir)?;

    let component_path = local_components_dir.join(format!("{}.rs", component_name));

    if component_path.exists() {
        println!("⚠️ Local override already exists: {}", component_path.display());
        return Ok(());
    }

    let template_content = format!(r#"//! Local override for {} component
//! This file has the highest precedence in the layered override system

use leptos::{{*, html::*}};

#[component]
pub fn {}() -> impl IntoView {{
    view! {{
        <div class="local-{component_name_lower}">
            <p>"Local override for {component_name} component"</p>
            // TODO: Add your custom implementation here
        </div>
    }}
}}
"#,
        component_name,
        component_name,
        component_name_lower = component_name.to_lowercase()
    );

    fs::write(&component_path, template_content)?;
    println!("  📝 Created: {}", component_path.display());

    // Also update the mod.rs file to export the component
    let mod_path = local_components_dir.join("mod.rs");
    let mod_content = if mod_path.exists() {
        format!("{}\npub mod {};", fs::read_to_string(&mod_path)?, component_name.to_lowercase())
    } else {
        format!(r#"//! Local component overrides
//! This module contains components that override template or feature components

pub mod {};
"#, component_name.to_lowercase())
    };

    fs::write(&mod_path, mod_content)?;

    Ok(())
}

/// Create a page override
async fn create_page_override(project_path: &Path, page_name: &str) -> Result<()> {
    let local_pages_dir = project_path.join("src/pages/local");
    fs::create_dir_all(&local_pages_dir)?;

    let page_path = local_pages_dir.join(format!("{}.rs", page_name));

    if page_path.exists() {
        println!("⚠️ Local override already exists: {}", page_path.display());
        return Ok(());
    }

    let template_content = format!(r#"//! Local override for {} page
//! This file has the highest precedence in the layered override system

use leptos::{{*, html::*}};

#[component]
pub fn {}Page() -> impl IntoView {{
    view! {{
        <div class="page-{page_name_lower}">
            <h1>"Local {} Page"</h1>
            <p>"This is a local override for the {} page"</p>
            // TODO: Add your custom page implementation here
        </div>
    }}
}}
"#,
        page_name,
        page_name,
        page_name_lower = page_name.to_lowercase(),
        page_name,
        page_name
    );

    fs::write(&page_path, template_content)?;
    println!("  📝 Created: {}", page_path.display());

    Ok(())
}

/// List all active overrides in the project
async fn list_active_overrides(path: Option<PathBuf>) -> Result<()> {
    let project_path = path.unwrap_or_else(|| PathBuf::from("."));

    println!("{}", style("📋 Active Local Overrides").bold().cyan());
    println!();

    let mut found_overrides = false;

    // Check for config overrides
    let config_local = project_path.join("config/local");
    if config_local.exists() {
        println!("{}", style("Configuration Overrides:").bold().yellow());
        for entry in fs::read_dir(&config_local)? {
            let entry = entry?;
            if entry.file_type()?.is_file() {
                println!("  ✅ {}", entry.file_name().to_string_lossy());
                found_overrides = true;
            }
        }
        println!();
    }

    // Check for component overrides
    let components_local = project_path.join("src/components/local");
    if components_local.exists() {
        println!("{}", style("Component Overrides:").bold().yellow());
        for entry in fs::read_dir(&components_local)? {
            let entry = entry?;
            if entry.file_type()?.is_file() {
                let filename = entry.file_name().to_string_lossy().to_string();
                if filename.ends_with(".rs") && filename != "mod.rs" {
                    println!("  ✅ {}", filename.strip_suffix(".rs").unwrap_or(&filename));
                    found_overrides = true;
                }
            }
        }
        println!();
    }

    // Check for page overrides
    let pages_local = project_path.join("src/pages/local");
    if pages_local.exists() {
        println!("{}", style("Page Overrides:").bold().yellow());
        for entry in fs::read_dir(&pages_local)? {
            let entry = entry?;
            if entry.file_type()?.is_file() {
                let filename = entry.file_name().to_string_lossy().to_string();
                if filename.ends_with(".rs") && filename != "mod.rs" {
                    println!("  ✅ {}", filename.strip_suffix(".rs").unwrap_or(&filename));
                    found_overrides = true;
                }
            }
        }
        println!();
    }

    if !found_overrides {
        println!("No local overrides found.");
        println!("💡 Use 'cargo rustelo override <type> <name>' to create overrides");
    }

    Ok(())
}

/// Trace how a configuration or component is resolved through layers
async fn trace_resolution(trace_type: &str, name: &str, path: Option<PathBuf>) -> Result<()> {
    let project_path = path.unwrap_or_else(|| PathBuf::from("."));

    println!("{} {} '{}'",
        style("🔍 Tracing resolution for:").bold().blue(),
        trace_type,
        style(name).yellow()
    );
    println!();

    match trace_type {
        "config" => trace_config_resolution(&project_path, name).await?,
        "component" => trace_component_resolution(&project_path, name).await?,
        "page" => trace_page_resolution(&project_path, name).await?,
        _ => {
            println!("⚠️ Unknown trace type: {}", trace_type);
            println!("📋 Available types: config, component, page");
            return Ok(());
        }
    }

    Ok(())
}

/// Trace configuration resolution
async fn trace_config_resolution(project_path: &Path, config_name: &str) -> Result<()> {
    println!("{}", style("Configuration Resolution Trace:").bold().cyan());

    // Define the resolution order
    let layers = [
        ("Local", project_path.join("config/local").join(config_name)),
        ("Features", project_path.join("config/features")), // This would need to check all feature subdirs
        ("Template", project_path.join("config/templates").join(config_name)),
        ("Framework", PathBuf::from("framework_defaults")), // Conceptual
    ];

    let mut found_winner = false;

    for (layer_name, layer_path) in &layers {
        let exists = if *layer_name == "Framework" {
            true // Framework always has defaults
        } else if *layer_name == "Features" {
            // Check if any feature has this config
            if layer_path.exists() {
                fs::read_dir(layer_path)?
                    .filter_map(|entry| entry.ok())
                    .any(|entry| entry.path().join(config_name).exists())
            } else {
                false
            }
        } else {
            layer_path.exists()
        };

        let icon = if exists && !found_winner {
            found_winner = true;
            "✅" // This one is used
        } else if exists {
            "🔸" // This one exists but is overridden
        } else {
            "❌" // This one doesn't exist
        };

        let status = if exists && icon == "✅" {
            style("USED").green().bold()
        } else if exists {
            style("OVERRIDDEN").yellow()
        } else {
            style("NOT FOUND").red()
        };

        println!("{} {} layer: {} - {}",
            icon,
            layer_name,
            layer_path.display(),
            status
        );
    }

    Ok(())
}

/// Trace component resolution
async fn trace_component_resolution(project_path: &Path, component_name: &str) -> Result<()> {
    println!("{}", style("Component Resolution Trace:").bold().cyan());

    let component_file = format!("{}.rs", component_name);

    let layers = [
        ("Local", project_path.join("src/components/local").join(&component_file)),
        ("Features", project_path.join("src/components/features")), // Would check all feature subdirs
        ("Template", project_path.join("src/components/templates").join(&component_file)),
        ("Framework", PathBuf::from("framework_components")), // Conceptual
    ];

    let mut found_winner = false;

    for (layer_name, layer_path) in &layers {
        let exists = if *layer_name == "Framework" {
            true // Framework components conceptually available
        } else if *layer_name == "Features" {
            // Check if any feature has this component
            if layer_path.exists() {
                fs::read_dir(layer_path)?
                    .filter_map(|entry| entry.ok())
                    .any(|entry| entry.path().join(&component_file).exists())
            } else {
                false
            }
        } else {
            layer_path.exists()
        };

        let icon = if exists && !found_winner {
            found_winner = true;
            "✅" // This one is used
        } else if exists {
            "🔸" // This one exists but is overridden
        } else {
            "❌" // This one doesn't exist
        };

        let status = if exists && icon == "✅" {
            style("USED").green().bold()
        } else if exists {
            style("OVERRIDDEN").yellow()
        } else {
            style("NOT FOUND").red()
        };

        println!("{} {} layer: {} - {}",
            icon,
            layer_name,
            layer_path.display(),
            status
        );
    }

    Ok(())
}

/// Trace page resolution
async fn trace_page_resolution(project_path: &Path, page_name: &str) -> Result<()> {
    println!("{}", style("Page Resolution Trace:").bold().cyan());

    let page_file = format!("{}.rs", page_name);

    let layers = [
        ("Local", project_path.join("src/pages/local").join(&page_file)),
        ("Features", project_path.join("src/pages/features")), // Would check all feature subdirs
        ("Template", project_path.join("src/pages/templates").join(&page_file)),
        ("Framework", PathBuf::from("framework_pages")), // Conceptual
    ];

    let mut found_winner = false;

    for (layer_name, layer_path) in &layers {
        let exists = if *layer_name == "Framework" {
            true // Framework pages conceptually available
        } else if *layer_name == "Features" {
            // Check if any feature has this page
            if layer_path.exists() {
                fs::read_dir(layer_path)?
                    .filter_map(|entry| entry.ok())
                    .any(|entry| entry.path().join(&page_file).exists())
            } else {
                false
            }
        } else {
            layer_path.exists()
        };

        let icon = if exists && !found_winner {
            found_winner = true;
            "✅" // This one is used
        } else if exists {
            "🔸" // This one exists but is overridden
        } else {
            "❌" // This one doesn't exist
        };

        let status = if exists && icon == "✅" {
            style("USED").green().bold()
        } else if exists {
            style("OVERRIDDEN").yellow()
        } else {
            style("NOT FOUND").red()
        };

        println!("{} {} layer: {} - {}",
            icon,
            layer_name,
            layer_path.display(),
            status
        );
    }

    Ok(())
}

/// Remove local override
async fn remove_local_override(override_type: &str, name: &str, path: Option<PathBuf>, force: bool) -> Result<()> {
    let project_path = path.unwrap_or_else(|| PathBuf::from("."));

    println!("{} {} '{}'",
        style("🗑️ Removing local override for:").bold().yellow(),
        override_type,
        style(name).red()
    );

    if !force {
        if !Confirm::with_theme(&ColorfulTheme::default())
            .with_prompt(&format!("Remove local override for {} '{}'?", override_type, name))
            .default(false)
            .interact()?
        {
            return Ok(());
        }
    }

    let override_path = match override_type {
        "config" => project_path.join("config/local").join(name),
        "component" => project_path.join("src/components/local").join(format!("{}.rs", name)),
        "page" => project_path.join("src/pages/local").join(format!("{}.rs", name)),
        _ => {
            println!("⚠️ Unknown override type: {}", override_type);
            return Ok(());
        }
    };

    if override_path.exists() {
        fs::remove_file(&override_path)?;
        println!("✅ Removed local override: {}", override_path.display());
        println!("💡 The next layer will now take effect");
    } else {
        println!("⚠️ No local override found for {} '{}'", override_type, name);
    }

    Ok(())
}