//! Foundation Discovery and Management Commands
//!
//! CLI commands for discovering and managing foundation pages and components
//! without local cloning/forking.

use std::path::PathBuf;

use rustelo_core::Result;

/// Handle foundation list command
pub async fn list(filter: Option<String>, format: String, force_in_source: bool) -> Result<()> {
    // Import the foundation discovery from rustelo_tools
    use rustelo_tools::build::foundation_discovery;

    // Check if running from Rustelo source and warn if not forced
    if foundation_discovery::is_running_from_rustelo_source() && !force_in_source {
        println!("{}", foundation_discovery::get_source_usage_warning());
        return Ok(());
    }

    println!("🔍 Discovering foundation items...");

    // Discover foundation items using the existing system
    let discovery = foundation_discovery::discover_foundation_items()
        .map_err(|e| rustelo_core::RusteloError::generic(format!("Discovery failed: {}", e)))?;

    let items: Vec<_> = match filter.as_deref() {
        Some("page") => discovery.get_items_by_type(foundation_discovery::FoundationItemType::Page),
        Some("component") => {
            discovery.get_items_by_type(foundation_discovery::FoundationItemType::Component)
        }
        Some("utility") => {
            discovery.get_items_by_type(foundation_discovery::FoundationItemType::Utility)
        }
        Some("type") => discovery.get_items_by_type(foundation_discovery::FoundationItemType::Type),
        _ => {
            // All items
            let mut all_items = Vec::new();
            all_items.extend(discovery.pages.values());
            all_items.extend(discovery.components.values());
            all_items.extend(discovery.utilities.values());
            all_items.extend(discovery.types.values());
            all_items
        }
    };

    // Sort items by type (Page -> Component -> Utility -> Type) then by name
    let mut sorted_items = items;
    sorted_items.sort_by(|a, b| {
        use foundation_discovery::FoundationItemType;

        // Define type order for sorting
        let type_order = |item_type: &FoundationItemType| -> u8 {
            match item_type {
                FoundationItemType::Page => 1,
                FoundationItemType::Component => 2,
                FoundationItemType::Utility => 3,
                FoundationItemType::Type => 4,
            }
        };

        // First sort by type, then by name
        let type_cmp = type_order(&a.item_type).cmp(&type_order(&b.item_type));
        if type_cmp == std::cmp::Ordering::Equal {
            a.name.cmp(&b.name)
        } else {
            type_cmp
        }
    });

    match format.as_str() {
        "json" => {
            let json = serde_json::to_string_pretty(&sorted_items).map_err(|e| {
                rustelo_core::RusteloError::generic(format!("JSON serialization failed: {}", e))
            })?;
            println!("{}", json);
        }
        "markdown" => {
            println!("# Foundation Items\n");
            for item in &sorted_items {
                println!("## {} ({:?})\n", item.name, item.item_type);
                println!("**Module**: `{}`", item.module_path);
                println!("**File**: `{}`", item.file_path.display());
                if let Some(doc) = &item.documentation {
                    println!("**Description**: {}", doc);
                }
                println!("**Signature**: `{}`\n", item.signature);
            }
        }
        _ => {
            // New 3-column layout: Name (35) | Type (14) | Info (78) - increased Type
            // column for "🛠️ Utility"
            println!("┌─{:─<35}─┬─{:─<14}─┬─{:─<78}─┐", "", "", "");
            println!("│ {:35} │ {:14} │ {:78} │", "Name", "Type", "Info");
            println!("├─{:─<35}─┼─{:─<14}─┼─{:─<78}─┤", "", "", "");

            let mut current_type: Option<&foundation_discovery::FoundationItemType> = None;

            for item in &sorted_items {
                // Add type separator if type changed
                if current_type.is_none() || current_type.unwrap() != &item.item_type {
                    if current_type.is_some() {
                        // Add separator between types
                        println!("├─{:─<35}─┼─{:─<14}─┼─{:─<78}─┤", "", "", "");
                    }
                    current_type = Some(&item.item_type);
                }

                let (type_emoji, type_str, emoji_visual_extra) = match item.item_type {
                    foundation_discovery::FoundationItemType::Page => ("📄", "Page", 1),
                    foundation_discovery::FoundationItemType::Component => ("🧩", "Component", 1),
                    foundation_discovery::FoundationItemType::Utility => ("🛠️", "Utility", 0),
                    foundation_discovery::FoundationItemType::Type => ("🏷️", "Type", 0),
                };

                let description = item
                    .documentation
                    .as_ref()
                    .map(|doc| doc.lines().next().unwrap_or("").trim())
                    .unwrap_or("No description");

                // Truncate description to fit in 78 chars (reduced from 80 due to wider Type
                // column)
                let truncated_desc = if description.len() > 76 {
                    format!("{}...", &description[..73])
                } else {
                    description.to_string()
                };

                // Format the type column with proper padding accounting for emoji width
                // Emojis visually take 2 chars but count as 1 in string length
                // So we need to pad manually to align properly (14 chars total)
                let type_content = format!("{} {}", type_emoji, type_str);
                // Each emoji takes 2 visual spaces but only 1 character count
                // let emoji_visual_extra = 1; // The extra space emojis take visually
                let visual_width = type_content.chars().count() + emoji_visual_extra;
                let padding_needed = 14usize.saturating_sub(visual_width);
                let formatted_type = format!("{}{}", type_content, " ".repeat(padding_needed));

                // Print main row with description
                println!(
                    "│ {:35} │ {} │ {:78} │",
                    item.name, formatted_type, truncated_desc
                );

                // Print module path row (indented, no type column content)
                println!("│ {:35} │ {:14} │ {:78} │", "", "", item.module_path);
            }

            println!("└─{:─<35}─┴─{:─<14}─┴─{:─<78}─┘", "", "", "");
            println!("\nFound {} items", sorted_items.len());
        }
    }

    Ok(())
}

/// Handle foundation search command
pub async fn search(query: String, include_docs: bool, force_in_source: bool) -> Result<()> {
    use rustelo_tools::build::foundation_discovery;

    // Check if running from Rustelo source and warn if not forced
    if foundation_discovery::is_running_from_rustelo_source() && !force_in_source {
        println!("{}", foundation_discovery::get_source_usage_warning());
        return Ok(());
    }

    let discovery = foundation_discovery::discover_foundation_items()
        .map_err(|e| rustelo_core::RusteloError::generic(format!("Discovery failed: {}", e)))?;
    let query_lower = query.to_lowercase();

    let mut matches = Vec::new();

    // Search in all items
    for item in discovery
        .pages
        .values()
        .chain(discovery.components.values())
        .chain(discovery.utilities.values())
        .chain(discovery.types.values())
    {
        let mut is_match = false;

        // Search in name
        if item.name.to_lowercase().contains(&query_lower) {
            is_match = true;
        }

        // Search in module path
        if item.module_path.to_lowercase().contains(&query_lower) {
            is_match = true;
        }

        // Search in documentation if requested
        if include_docs {
            if let Some(doc) = &item.documentation {
                if doc.to_lowercase().contains(&query_lower) {
                    is_match = true;
                }
            }
        }

        // Search in signature
        if item.signature.to_lowercase().contains(&query_lower) {
            is_match = true;
        }

        if is_match {
            matches.push(item);
        }
    }

    if matches.is_empty() {
        println!("❌ No matching foundation items found for '{}'", query);
        return Ok(());
    }

    println!("✅ Found {} matching items:\n", matches.len());

    for item in matches {
        let type_str = match item.item_type {
            foundation_discovery::FoundationItemType::Page => "📄 Page",
            foundation_discovery::FoundationItemType::Component => "🧩 Component",
            foundation_discovery::FoundationItemType::Utility => "🛠️ Utility",
            foundation_discovery::FoundationItemType::Type => "🏷️ Type",
        };

        println!("{} {}", type_str, item.name);
        println!("  Module: {}", item.module_path);
        if let Some(doc) = &item.documentation {
            println!("  Description: {}", doc.lines().next().unwrap_or("").trim());
        }
        println!("  Signature: {}\n", item.signature);
    }

    Ok(())
}

/// Handle foundation info command
pub async fn info(name: String, force_in_source: bool) -> Result<()> {
    use rustelo_tools::build::foundation_discovery;

    // Check if running from Rustelo source and warn if not forced
    if foundation_discovery::is_running_from_rustelo_source() && !force_in_source {
        println!("{}", foundation_discovery::get_source_usage_warning());
        return Ok(());
    }

    let discovery = foundation_discovery::discover_foundation_items()
        .map_err(|e| rustelo_core::RusteloError::generic(format!("Discovery failed: {}", e)))?;

    if let Some(item) = discovery.get_item(&name) {
        let type_str = match item.item_type {
            foundation_discovery::FoundationItemType::Page => "📄 Page",
            foundation_discovery::FoundationItemType::Component => "🧩 Component",
            foundation_discovery::FoundationItemType::Utility => "🛠️ Utility",
            foundation_discovery::FoundationItemType::Type => "🏷️ Type",
        };

        println!("# {} {}\n", type_str, item.name);
        println!("**Module**: `{}`", item.module_path);
        println!("**File**: `{}`", item.file_path.display());
        println!(
            "**Is Leptos Component**: {}",
            if item.is_component { "Yes" } else { "No" }
        );

        if let Some(doc) = &item.documentation {
            println!("\n**Documentation**:");
            for line in doc.lines() {
                println!("  {}", line);
            }
        }

        println!("\n**Signature**:");
        println!("```rust");
        println!("{}", item.signature);
        println!("```");

        if !item.dependencies.is_empty() {
            println!("\n**Dependencies**: {}", item.dependencies.join(", "));
        }
    } else {
        println!("❌ Foundation item '{}' not found", name);
        println!("💡 Use 'cargo rustelo foundation list' to see all available items");
    }

    Ok(())
}

/// Handle foundation clear cache command
pub async fn clear_cache(force_in_source: bool) -> Result<()> {
    use rustelo_tools::build::foundation_discovery;
    use rustelo_tools::smart_cache::SmartCache;

    // Check if running from Rustelo source and warn if not forced
    if foundation_discovery::is_running_from_rustelo_source() && !force_in_source {
        println!("{}", foundation_discovery::get_source_usage_warning());
        return Ok(());
    }

    // Clear the smart cache for foundation discovery
    match SmartCache::new("foundation-discovery") {
        Ok(cache) => {
            let cache_root = cache.cache_root();
            if cache_root.exists() {
                std::fs::remove_dir_all(cache_root).map_err(|e| {
                    rustelo_core::RusteloError::generic(format!("Failed to clear cache: {}", e))
                })?;
                println!("✅ Foundation discovery cache cleared");
            } else {
                println!("ℹ️ Foundation discovery cache was already empty");
            }
        }
        Err(e) => {
            println!("⚠️ Could not access foundation discovery cache: {}", e);
        }
    }

    Ok(())
}

/// Handle foundation check updates command
pub async fn check_updates(force_in_source: bool) -> Result<()> {
    use rustelo_tools::build::foundation_discovery;
    use rustelo_tools::smart_cache::SmartCache;

    // Check if running from Rustelo source and warn if not forced
    if foundation_discovery::is_running_from_rustelo_source() && !force_in_source {
        println!("{}", foundation_discovery::get_source_usage_warning());
        return Ok(());
    }

    println!("🔍 Checking foundation for updates...");

    // Force fresh discovery by clearing cache first
    if let Ok(cache) = SmartCache::new("foundation-discovery") {
        let cache_root = cache.cache_root();
        if cache_root.exists() {
            let _ = std::fs::remove_dir_all(cache_root);
        }
    }

    // Run discovery to get latest state
    let discovery = foundation_discovery::discover_foundation_items()
        .map_err(|e| rustelo_core::RusteloError::generic(format!("Discovery failed: {}", e)))?;

    let total_items = discovery.pages.len()
        + discovery.components.len()
        + discovery.utilities.len()
        + discovery.types.len();

    println!("✅ Foundation scan complete:");
    println!("  📄 Pages: {}", discovery.pages.len());
    println!("  🧩 Components: {}", discovery.components.len());
    println!("  🛠️ Utilities: {}", discovery.utilities.len());
    println!("  🏷️ Types: {}", discovery.types.len());
    println!("  📊 Total: {} items", total_items);
    println!("  🕒 Discovered at: {}", discovery.discovered_at);

    println!("\n💡 Use 'cargo rustelo foundation list' to see all available items");

    Ok(())
}

/// Test virtual resolution for a specific page or component
pub async fn test_resolution(name: String, item_type: String, force_in_source: bool) -> Result<()> {
    use rustelo_tools::build::foundation_discovery;
    use rustelo_tools::build::virtual_resolution::{ResolvedItemType, VirtualResolver};

    // Check if running from Rustelo source and warn if not forced
    if foundation_discovery::is_running_from_rustelo_source() && !force_in_source {
        println!("{}", foundation_discovery::get_source_usage_warning());
        return Ok(());
    }

    println!(
        "🧪 Testing virtual resolution for: {} (type: {})",
        name, item_type
    );

    let resolver = VirtualResolver::new().map_err(|e| {
        rustelo_core::RusteloError::generic(format!("Failed to create resolver: {}", e))
    })?;

    let resolved_type = match item_type.as_str() {
        "page" => ResolvedItemType::Page,
        "component" => ResolvedItemType::Component,
        "utility" => ResolvedItemType::Utility,
        "type" => ResolvedItemType::Type,
        _ => {
            println!("❌ Invalid item type. Use: page, component, utility, type");
            return Ok(());
        }
    };

    match resolver.resolve_item(&name, resolved_type) {
        Ok(resolution) => {
            println!("✅ Virtual resolution successful!\n");

            println!("📋 Resolution Details:");
            println!("  Item: {}", resolution.item.name);
            println!("  Type: {:?}", resolution.item.item_type);
            println!("  Source: {:?}", resolution.item.source);
            println!("  File Path: {}", resolution.item.file_path.display());
            println!("  Import Path: {}", resolution.item.import_path);
            println!("  Needs Generation: {}", resolution.needs_generation);

            if !resolution.item.dependencies.is_empty() {
                println!(
                    "  Dependencies: {}",
                    resolution.item.dependencies.join(", ")
                );
            }

            println!("\n🔍 Resolution Trace:");
            for (i, step) in resolution.resolution_path.iter().enumerate() {
                let status = if step.found { "✅" } else { "❌" };
                println!(
                    "  {}. {} {:?} - {} ({})",
                    i + 1,
                    status,
                    step.source,
                    step.path_checked.display(),
                    step.reason
                );
            }

            if resolution.needs_generation {
                println!("\n🛠️ Generation Preview:");
                if let Some(content) = &resolution.item.content {
                    println!("```rust");
                    // Show first 10 lines
                    for (i, line) in content.lines().take(10).enumerate() {
                        println!("{:2}: {}", i + 1, line);
                    }
                    if content.lines().count() > 10 {
                        println!("... ({} more lines)", content.lines().count() - 10);
                    }
                    println!("```");
                }

                println!("\n💡 To apply this resolution, run:");
                println!("   cargo build  # Will automatically apply during build");
            } else {
                println!("\n✅ Item already exists, no generation needed");
            }
        }
        Err(e) => {
            println!("❌ Virtual resolution failed: {}", e);
        }
    }

    Ok(())
}

/// Import/copy a foundation item to the local project
pub async fn import(
    name: String,
    item_type: String,
    target_path: Option<PathBuf>,
    force_in_source: bool,
) -> Result<()> {
    use rustelo_tools::build::foundation_discovery;
    use rustelo_tools::build::virtual_resolution::{ResolvedItemType, VirtualResolver};

    // Check if running from Rustelo source and warn if not forced
    if foundation_discovery::is_running_from_rustelo_source() && !force_in_source {
        println!("{}", foundation_discovery::get_source_usage_warning());
        return Ok(());
    }

    println!(
        "📥 Importing foundation item: {} (type: {})",
        name, item_type
    );

    let resolver = VirtualResolver::new().map_err(|e| {
        rustelo_core::RusteloError::generic(format!("Failed to create resolver: {}", e))
    })?;

    let resolved_type = match item_type.as_str() {
        "page" => ResolvedItemType::Page,
        "component" => ResolvedItemType::Component,
        "utility" => ResolvedItemType::Utility,
        "type" => ResolvedItemType::Type,
        _ => {
            println!("❌ Invalid item type. Use: page, component, utility, type");
            return Ok(());
        }
    };

    match resolver.resolve_item(&name, resolved_type) {
        Ok(resolution) => {
            // Override the file path if target_path is provided
            let mut modified_resolution = resolution;
            if let Some(target) = target_path {
                modified_resolution.item.file_path = target;
                modified_resolution.needs_generation = true;
            }

            // Apply the resolution (generate/copy files)
            resolver
                .apply_resolution(&modified_resolution)
                .map_err(|e| {
                    rustelo_core::RusteloError::generic(format!("Failed to import: {}", e))
                })?;

            println!(
                "✅ Successfully imported '{}' to: {}",
                name,
                modified_resolution.item.file_path.display()
            );

            match modified_resolution.item.source {
                rustelo_tools::build::virtual_resolution::ResolutionSource::Foundation => {
                    println!("  🔗 Source: Foundation (virtual reference)");
                    println!("  💡 This creates a wrapper that imports from foundation");
                    println!("  🛠️ You can customize it by editing the generated file");
                }
                rustelo_tools::build::virtual_resolution::ResolutionSource::Generated => {
                    println!("  🏗️ Source: Generated boilerplate");
                    println!("  💡 Customize this template to fit your needs");
                }
                _ => {
                    println!("  📁 Source: {:?}", modified_resolution.item.source);
                }
            }
        }
        Err(e) => {
            return Err(rustelo_core::RusteloError::generic(format!(
                "Import failed: {}",
                e
            )));
        }
    }

    Ok(())
}
