//! Unified CLI commands for Rustelo Tools

#[cfg(feature = "cli")]
use clap::{Parser, Subcommand};

/// Rustelo Tools CLI
#[derive(Parser)]
#[command(name = "rustelo-tools")]
#[command(about = "Comprehensive development tools for Rustelo framework")]
#[command(version)]
pub struct Cli {
    #[command(subcommand)]
    pub command: Commands,
}

/// Available commands
#[derive(Subcommand)]
pub enum Commands {
    /// Analyze project structure and generate documentation
    Analyze {
        /// Output format (markdown, json, toml)
        #[arg(short, long, default_value = "markdown")]
        format: String,

        /// Output directory
        #[arg(short, long, default_value = "target/site_build/info")]
        output: String,
    },

    /// Generate code (routes, pages, components)
    Generate {
        /// What to generate
        #[arg(value_enum)]
        target: GenerateTarget,

        /// Name for the generated item
        name: String,

        /// Template to use
        #[arg(short, long)]
        template: Option<String>,
    },

    /// Discover and manage foundation pages and components
    Foundation {
        #[command(subcommand)]
        action: FoundationCommands,
    },

    /// Interactive page manager (TUI)
    Manage {
        /// Start in specific mode
        #[arg(short, long)]
        mode: Option<String>,
    },

    /// Publish and sync operations
    Publish {
        #[command(subcommand)]
        action: PublishCommands,
    },

    /// Documentation operations
    Docs {
        #[command(subcommand)]
        action: DocsCommands,
    },
}

#[derive(clap::ValueEnum, Clone)]
pub enum GenerateTarget {
    Route,
    Page,
    Component,
    Template,
}

#[derive(Subcommand)]
pub enum FoundationCommands {
    /// List all available foundation pages and components
    List {
        /// Filter by type (page, component, utility, type)
        #[arg(short, long)]
        filter: Option<String>,

        /// Output format (table, json, markdown)
        #[arg(short, long, default_value = "table")]
        format: String,
    },
    /// Search for specific foundation items
    Search {
        /// Search query
        query: String,

        /// Search in documentation too
        #[arg(short, long)]
        include_docs: bool,
    },
    /// Show detailed information about a foundation item
    Info {
        /// Item name to inspect
        name: String,
    },
    /// Clear foundation discovery cache
    ClearCache,
    /// Check for foundation updates
    CheckUpdates,
    /// Test virtual resolution for an item
    TestResolution {
        /// Item name to test resolution for
        name: String,
        /// Item type (page, component, utility, type)
        #[arg(short, long, default_value = "page")]
        item_type: String,
    },
}

#[derive(Subcommand)]
pub enum PublishCommands {
    /// Sync with main Rustelo project
    Sync {
        /// What to sync (templates, components, docs)
        target: String,
    },
    /// Package for distribution
    Package {
        /// Output format
        #[arg(short, long, default_value = "crate")]
        format: String,
    },
}

#[derive(Subcommand)]
pub enum DocsCommands {
    /// Generate documentation
    Generate {
        /// Include private items
        #[arg(long)]
        include_private: bool,
    },
    /// Serve documentation locally
    Serve {
        /// Port to serve on
        #[arg(short, long, default_value = "8080")]
        port: u16,
    },
    /// Deploy documentation
    Deploy {
        /// Deployment target
        target: String,
    },
}

/// Main CLI handler
pub fn run_cli() -> anyhow::Result<()> {
    use std::path::Path;

    use clap::Parser;

    let cli = Cli::parse();

    match cli.command {
        Commands::Analyze { format, output } => handle_analyze_command(&format, &output),

        Commands::Generate {
            target,
            name,
            template,
        } => handle_generate_command(target, &name, template.as_deref()),

        Commands::Foundation { action } => handle_foundation_command(action),

        Commands::Manage { mode } => handle_manage_command(mode.as_deref()),

        Commands::Publish { action } => handle_publish_command(action),

        Commands::Docs { action } => handle_docs_command(action),
    }
}

/// Handle analyze command
fn handle_analyze_command(_format: &str, output: &str) -> anyhow::Result<()> {
    println!("🔍 Analyzing project structure...");

    // For now, provide a basic project analysis since comprehensive analysis
    // is build-time only and has been moved to build-tools crate
    println!("📋 Runtime Project Analysis (Basic)");
    println!("==================================");

    // Basic runtime analysis that doesn't require build-time dependencies
    analyze_project_basic(output)?;

    println!("✅ Basic analysis complete! For comprehensive analysis,");
    println!("   use the build-time tools during compilation or");
    println!("   run 'just build' to trigger comprehensive analysis.");

    Ok(())
}

/// Handle generate command
fn handle_generate_command(
    target: GenerateTarget,
    name: &str,
    template: Option<&str>,
) -> anyhow::Result<()> {
    let template_name = template.unwrap_or("basic");

    match target {
        GenerateTarget::Route => {
            println!(
                "🛣️ Generating route: {} (template: {})",
                name, template_name
            );
            generate_route_scaffolding(name, template_name)?;
        }
        GenerateTarget::Page => {
            println!("📄 Generating page: {} (template: {})", name, template_name);
            generate_page_scaffolding(name, template_name)?;
        }
        GenerateTarget::Component => {
            println!(
                "🧩 Generating component: {} (template: {})",
                name, template_name
            );
            generate_component_scaffolding(name, template_name)?;
        }
        GenerateTarget::Template => {
            println!("📋 Generating template: {}", name);
            generate_template_scaffolding(name)?;
        }
    }

    Ok(())
}

/// Handle foundation command
fn handle_foundation_command(action: FoundationCommands) -> anyhow::Result<()> {
    match action {
        FoundationCommands::List { filter, format } => {
            println!("🔍 Discovering foundation items...");
            super::foundation_cli::handle_foundation_list(filter.as_deref(), &format)?;
        }
        FoundationCommands::Search {
            query,
            include_docs,
        } => {
            println!("🔍 Searching foundation for: '{}'", query);
            super::foundation_cli::handle_foundation_search(&query, include_docs)?;
        }
        FoundationCommands::Info { name } => {
            println!("📋 Getting info for: {}", name);
            super::foundation_cli::handle_foundation_info(&name)?;
        }
        FoundationCommands::ClearCache => {
            println!("🧹 Clearing foundation discovery cache...");
            super::foundation_cli::handle_foundation_clear_cache()?;
        }
        FoundationCommands::CheckUpdates => {
            println!("🔄 Checking for foundation updates...");
            super::foundation_cli::handle_foundation_check_updates()?;
        }
        FoundationCommands::TestResolution { name, item_type } => {
            println!(
                "🧪 Testing virtual resolution for: {} (type: {})",
                name, item_type
            );
            super::foundation_cli::handle_virtual_resolution_test(&name, &item_type)?;
        }
    }
    Ok(())
}

/// Handle manage command
fn handle_manage_command(mode: Option<&str>) -> anyhow::Result<()> {
    println!("🎛️ Starting Rustelo Tools Manager...");

    match mode {
        Some("dashboard") | None => {
            println!("📊 Launching dashboard mode...");
            #[cfg(feature = "cli")]
            super::dashboard::run_dashboard()?;
            #[cfg(not(feature = "cli"))]
            println!("❌ CLI features not enabled. Build with --features cli");
        }
        Some("editor") => {
            println!("✏️ Launching editor mode...");
            #[cfg(feature = "cli")]
            super::simple_editor::run_editor()?;
            #[cfg(not(feature = "cli"))]
            println!("❌ CLI features not enabled. Build with --features cli");
        }
        Some(other) => {
            println!(
                "❌ Unknown mode: {}. Available modes: dashboard, editor",
                other
            );
            return Ok(());
        }
    }

    Ok(())
}

/// Handle publish command
fn handle_publish_command(action: PublishCommands) -> anyhow::Result<()> {
    #[cfg(feature = "publishing")]
    match action {
        PublishCommands::Sync { target } => {
            println!("🔄 Syncing {} with Rustelo project...", target);
            crate::publishing::sync::sync_with_rustelo(&target)?;
            println!("✅ Sync complete!");
        }
        PublishCommands::Package { format } => {
            println!("📦 Packaging project for distribution ({})...", format);
            crate::publishing::package::create_package(&format)?;
            println!("✅ Package created!");
        }
    }

    #[cfg(not(feature = "publishing"))]
    {
        println!("❌ Publishing features not enabled. Build with --features publishing");
        let _ = action; // Silence unused warning
    }

    Ok(())
}

/// Handle docs command
fn handle_docs_command(action: DocsCommands) -> anyhow::Result<()> {
    match action {
        DocsCommands::Generate { include_private } => {
            println!(
                "📚 Generating documentation (private: {})...",
                include_private
            );
            generate_docs(include_private)?;
            println!("✅ Documentation generated!");
        }
        DocsCommands::Serve { port } => {
            println!("🌐 Serving documentation on http://localhost:{}", port);
            serve_docs(port)?;
        }
        DocsCommands::Deploy { target } => {
            println!("🚀 Deploying documentation to {}...", target);
            #[cfg(feature = "publishing")]
            crate::publishing::deploy::deploy_docs(&target)?;
            #[cfg(not(feature = "publishing"))]
            println!("❌ Publishing features not enabled. Build with --features publishing");
            println!("✅ Documentation deployed!");
        }
    }

    Ok(())
}

// Generation helper functions
pub fn generate_route_scaffolding(name: &str, _template: &str) -> anyhow::Result<()> {
    println!("  📝 Creating route files for: {}", name);

    create_basic_route_file(name)?;

    Ok(())
}

pub fn generate_page_scaffolding(name: &str, _template: &str) -> anyhow::Result<()> {
    println!("  📝 Creating page files for: {}", name);

    create_basic_page_file(name)?;

    Ok(())
}

pub fn generate_component_scaffolding(name: &str, _template: &str) -> anyhow::Result<()> {
    println!("  📝 Creating component files for: {}", name);

    create_basic_component_file(name)?;

    Ok(())
}

pub fn generate_template_scaffolding(name: &str) -> anyhow::Result<()> {
    println!("  📝 Creating template: {}", name);

    let template_dir =
        std::env::var("SITE_TEMPLATES_PATH").unwrap_or_else(|_| "site/templates".to_string());

    std::fs::create_dir_all(&template_dir)?;

    let template_content = r#"<!DOCTYPE html>
<html>
<head>
    <title>{{ title | default(value="Rustelo") }}</title>
</head>
<body>
    <h1>{{ heading | default(value="Welcome") }}</h1>
    <main>
        {{ content | safe }}
    </main>
</body>
</html>"#;

    let template_path = format!("{}/{}.tera", template_dir, name);
    std::fs::write(&template_path, template_content)?;
    println!("  ✅ Template created: {}", template_path);

    Ok(())
}

// Basic file creation functions
fn create_basic_route_file(name: &str) -> anyhow::Result<()> {
    let route_content = format!(
        r#"//! {} route handler

use axum::{{response::Html, routing::get, Router}};

pub fn router() -> Router {{
    Router::new().route("/{}"', get(handle_{}))
}}

pub async fn handle_{}() -> Html<&'static str> {{
    Html("<h1>{} Route</h1>")
}}
"#,
        name,
        name.to_lowercase(),
        name.to_lowercase(),
        name.to_lowercase(),
        name
    );

    std::fs::create_dir_all("src/routes")?;
    std::fs::write(
        format!("src/routes/{}.rs", name.to_lowercase()),
        route_content,
    )?;
    println!(
        "  ✅ Basic route created: src/routes/{}.rs",
        name.to_lowercase()
    );
    Ok(())
}

fn create_basic_page_file(name: &str) -> anyhow::Result<()> {
    let page_content = format!(
        r#"//! {} page component

use leptos::*;

#[component]
pub fn {}Page() -> impl IntoView {{
    view! {{
        <div class="page-{}">
            <h1>"{}"</h1>
            <p>"Welcome to the {} page."</p>
        </div>
    }}
}}
"#,
        name,
        name,
        name.to_lowercase(),
        name,
        name
    );

    std::fs::create_dir_all("src/pages")?;
    std::fs::write(
        format!("src/pages/{}.rs", name.to_lowercase()),
        page_content,
    )?;
    println!(
        "  ✅ Basic page created: src/pages/{}.rs",
        name.to_lowercase()
    );
    Ok(())
}

fn create_basic_component_file(name: &str) -> anyhow::Result<()> {
    let component_content = format!(
        r#"//! {} component

use leptos::*;

#[component]
pub fn {}(#[prop(optional)] class: Option<String>) -> impl IntoView {{
    let class = class.unwrap_or_default();

    view! {{
        <div class={{format!("component-{} {{}}", class)}}>
            <span>"{}"</span>
        </div>
    }}
}}
"#,
        name,
        name,
        name.to_lowercase(),
        name
    );

    std::fs::create_dir_all("src/components")?;
    std::fs::write(
        format!("src/components/{}.rs", name.to_lowercase()),
        component_content,
    )?;
    println!(
        "  ✅ Basic component created: src/components/{}.rs",
        name.to_lowercase()
    );
    Ok(())
}

// Documentation functions
fn generate_docs(include_private: bool) -> anyhow::Result<()> {
    println!("  📖 Running cargo doc...");

    let mut cmd = std::process::Command::new("cargo");
    cmd.args(["doc", "--no-deps"]);

    if include_private {
        cmd.arg("--document-private-items");
    }

    let output = cmd.output()?;

    if output.status.success() {
        println!("  ✅ Documentation generated successfully!");
        println!("  🌐 View at: target/doc/index.html");
    } else {
        println!("  ❌ Documentation generation failed:");
        println!("{}", String::from_utf8_lossy(&output.stderr));
    }

    Ok(())
}

fn serve_docs(port: u16) -> anyhow::Result<()> {
    println!("  🌐 Starting documentation server...");
    println!("  📁 Serving from: target/doc/");

    // Check if documentation exists
    if !std::path::Path::new("target/doc").exists() {
        println!("  ⚠️ No documentation found. Generating first...");
        generate_docs(false)?;
    }

    // Simple HTTP server for documentation
    println!("  🔗 Open http://localhost:{} to view documentation", port);
    println!("  ⏹️ Press Ctrl+C to stop server");

    // Use Python's built-in server if available, otherwise suggest alternatives
    let server_cmd = std::process::Command::new("python3")
        .args(["-m", "http.server", &port.to_string()])
        .current_dir("target/doc")
        .status();

    match server_cmd {
        Ok(_) => println!("  ✅ Documentation server stopped"),
        Err(_) => {
            println!("  ⚠️ Python3 not available. Install a static file server:");
            println!("     cargo install basic-http-server");
            println!("     basic-http-server target/doc -a 127.0.0.1:{}", port);
        }
    }

    Ok(())
}
/// Basic runtime project analysis (does not require build-time dependencies)
pub fn analyze_project_basic(output: &str) -> anyhow::Result<()> {
    use std::fs;
    use std::path::Path;

    // Resolve output path using environment variables if using default
    let resolved_output = if output == "target/site_build/info" {
        std::env::var("SITE_INFO_PATH").unwrap_or_else(|_| output.to_string())
    } else {
        output.to_string()
    };

    println!("📁 Project Structure:");

    // Check key directories
    let directories = [
        ("crates/", "Workspace crates"),
        ("site/", "Site content"),
        ("site/config/", "Configuration"),
        ("site/templates/", "Templates"),
        ("target/", "Build artifacts"),
    ];

    for (dir, desc) in &directories {
        let exists = Path::new(dir).exists();
        let status = if exists { "✅" } else { "❌" };
        println!("  {} {:<20} - {}", status, dir, desc);
    }

    // Check key files
    println!("\n📄 Key Files:");
    let files = [
        ("Cargo.toml", "Workspace manifest"),
        ("justfile", "Task runner"),
        ("package.json", "Node dependencies"),
        ("uno.config.ts", "CSS framework"),
    ];

    for (file, desc) in &files {
        let exists = Path::new(file).exists();
        let status = if exists { "✅" } else { "❌" };
        println!("  {} {:<15} - {}", status, file, desc);
    }

    // Create basic report if output directory specified
    if resolved_output != "." {
        if let Err(e) = fs::create_dir_all(&resolved_output) {
            eprintln!("⚠️ Could not create output directory: {}", e);
            return Ok(());
        }

        let report_path = Path::new(&resolved_output).join("basic_analysis.md");
        let report_content = format!(
            "# Basic Project Analysis\n\nGenerated: {}\n\n## Project Structure\n\nBasic analysis \
             completed. For comprehensive analysis, run the build process.\n",
            chrono::Utc::now().format("%Y-%m-%d %H:%M:%S UTC")
        );

        if let Err(e) = fs::write(&report_path, report_content) {
            eprintln!("⚠️ Could not write analysis report: {}", e);
        } else {
            println!("\n📋 Basic report saved: {}", report_path.display());
        }
    }

    Ok(())
}
