//! Build pipeline command implementations

use std::collections::HashMap;
use std::path::PathBuf;

use rustelo_core::{
    assets::AssetCategory,
    build::{BuildConfig, BuildPipeline, BuildTarget},
    config::RusteloConfig,
    Result,
};

/// Initialize build pipeline configuration
pub async fn init(force: bool) -> Result<()> {
    tracing::info!("Initializing build pipeline configuration");

    let config_path = "rustelo-build.toml";

    if std::path::Path::new(config_path).exists() && !force {
        println!("⚠️  Build configuration already exists at: {}", config_path);
        println!("💡 Use --force to overwrite existing configuration");
        return Ok(());
    }

    let config = BuildConfig::default();
    BuildPipeline::save_build_config(&config, config_path)?;

    println!(
        "✅ Build pipeline configuration initialized: {}",
        config_path
    );
    println!("📋 Default targets created:");
    for (name, target) in &config.targets {
        println!("  {} -> {}", name, target.output_dir.display());
    }

    Ok(())
}

/// List available build targets
pub async fn targets() -> Result<()> {
    tracing::info!("Listing build targets");

    let config_path = "rustelo-build.toml";
    let config = if std::path::Path::new(config_path).exists() {
        BuildPipeline::load_build_config(config_path)?
    } else {
        println!("⚠️  No build configuration found. Run `rustelo pipeline init` first.");
        return Ok(());
    };

    println!("📋 Available Build Targets:");

    for (name, target) in &config.targets {
        println!("\n  🎯 {}", name);
        println!("     Output: {}", target.output_dir.display());
        println!("     Categories: {:?}", target.asset_categories);

        if !target.variables.is_empty() {
            println!("     Variables:");
            for (key, value) in &target.variables {
                println!("       {}={}", key, value);
            }
        }

        if let Some(ref hooks) = target.hooks {
            let hook_count =
                hooks.pre_build.len() + hooks.post_assets.len() + hooks.post_build.len();
            if hook_count > 0 {
                println!("     Hooks: {} configured", hook_count);
            }
        }

        println!("     Organize by category: {}", target.organize_by_category);
    }

    Ok(())
}

/// Run a specific build target
pub async fn run(target_name: &str, vars: Option<Vec<String>>) -> Result<()> {
    tracing::info!("Running build target: {}", target_name);

    let config_path = "rustelo-build.toml";
    let mut build_config = if std::path::Path::new(config_path).exists() {
        BuildPipeline::load_build_config(config_path)?
    } else {
        println!("⚠️  No build configuration found. Creating default configuration...");
        let config = BuildConfig::default();
        BuildPipeline::save_build_config(&config, config_path)?;
        config
    };

    // Parse additional variables
    if let Some(var_strings) = vars {
        if let Some(target) = build_config.targets.get_mut(target_name) {
            for var_string in var_strings {
                if let Some((key, value)) = var_string.split_once('=') {
                    target.variables.insert(key.to_string(), value.to_string());
                    tracing::info!("Added variable: {}={}", key, value);
                } else {
                    tracing::warn!("Invalid variable format: {}", var_string);
                }
            }
        }
    }

    // Load framework config and run pipeline
    let rustelo_config = RusteloConfig::load().unwrap_or_default();
    let pipeline = BuildPipeline::new(rustelo_config, build_config);

    let _start_time = std::time::Instant::now();
    let result = pipeline.build_target(target_name).await?;

    println!("✅ Build target '{}' completed successfully", target_name);
    println!("   Assets processed: {}", result.assets_processed);
    println!("   Duration: {:.2}s", result.duration.as_secs_f64());

    if result.cache_hits > 0 {
        println!("   Cache hits: {}", result.cache_hits);
    }

    Ok(())
}

/// Show build configuration
pub async fn config(target_filter: Option<String>) -> Result<()> {
    tracing::info!("Showing build configuration");

    let config_path = "rustelo-build.toml";
    let config = if std::path::Path::new(config_path).exists() {
        BuildPipeline::load_build_config(config_path)?
    } else {
        println!("⚠️  No build configuration found at: {}", config_path);
        println!("💡 Run `rustelo pipeline init` to create a default configuration");
        return Ok(());
    };

    println!("🔧 Build Configuration ({})", config_path);

    // Show global settings
    if !config.hooks.pre_build.is_empty()
        || !config.hooks.post_assets.is_empty()
        || !config.hooks.post_build.is_empty()
    {
        println!("\n📎 Global Hooks:");
        if !config.hooks.pre_build.is_empty() {
            println!("  Pre-build: {:?}", config.hooks.pre_build);
        }
        if !config.hooks.post_assets.is_empty() {
            println!("  Post-assets: {:?}", config.hooks.post_assets);
        }
        if !config.hooks.post_build.is_empty() {
            println!("  Post-build: {:?}", config.hooks.post_build);
        }
    }

    // Show asset configuration
    println!("\n📦 Asset Configuration:");
    println!("  Enabled: {}", config.assets.enabled);
    println!("  Watch enabled: {}", config.assets.watch_enabled);
    println!("  Concurrency: {}", config.assets.concurrency);
    println!("  Incremental: {}", config.assets.incremental);

    // Show cache configuration
    println!("\n🗄️  Cache Configuration:");
    println!("  Enabled: {}", config.cache.enabled);
    println!("  Cache directory: {}", config.cache.cache_dir.display());
    println!("  Key strategy: {:?}", config.cache.key_strategy);
    println!("  Expire hours: {}", config.cache.expire_hours);

    // Show targets
    if let Some(ref filter) = target_filter {
        if let Some(target) = config.targets.get(filter) {
            println!("\n🎯 Target: {}", filter);
            show_target_details(target);
        } else {
            println!("\n❌ Target '{}' not found", filter);
        }
    } else {
        println!("\n🎯 Build Targets:");
        for (name, target) in &config.targets {
            println!("\n  Target: {}", name);
            show_target_details(target);
        }
    }

    Ok(())
}

/// Add a new build target
pub async fn add(name: &str, output: PathBuf, categories: Option<Vec<String>>) -> Result<()> {
    tracing::info!("Adding new build target: {}", name);

    let config_path = "rustelo-build.toml";
    let mut config = if std::path::Path::new(config_path).exists() {
        BuildPipeline::load_build_config(config_path)?
    } else {
        println!("⚠️  No build configuration found. Creating default configuration...");
        BuildConfig::default()
    };

    if config.targets.contains_key(name) {
        println!("⚠️  Target '{}' already exists", name);
        return Ok(());
    }

    // Parse asset categories
    let asset_categories = if let Some(category_names) = categories {
        let mut cats = Vec::new();
        for cat_name in category_names {
            match cat_name.to_lowercase().as_str() {
                "build" => cats.push(AssetCategory::Build),
                "config" => cats.push(AssetCategory::Config),
                "static" => cats.push(AssetCategory::Static),
                "content" => cats.push(AssetCategory::Content),
                "development" | "dev" => cats.push(AssetCategory::Development),
                "deployment" | "deploy" => cats.push(AssetCategory::Deployment),
                _ => {
                    println!("⚠️  Unknown category: {}", cat_name);
                    continue;
                }
            }
        }
        cats
    } else {
        // Default categories
        vec![
            AssetCategory::Static,
            AssetCategory::Content,
            AssetCategory::Config,
        ]
    };

    let target = BuildTarget {
        name: name.to_string(),
        output_dir: output.clone(),
        asset_categories,
        variables: {
            let mut vars = HashMap::new();
            vars.insert("target".to_string(), name.to_string());
            vars
        },
        hooks: None,
        organize_by_category: false,
        cross: None,
    };

    config.targets.insert(name.to_string(), target);

    // Save updated configuration
    BuildPipeline::save_build_config(&config, config_path)?;

    println!("✅ Added build target: {}", name);
    println!("   Output: {}", output.display());
    println!("   Categories: {:?}", config.targets[name].asset_categories);

    Ok(())
}

/// Show details for a build target
fn show_target_details(target: &BuildTarget) {
    println!("    Output directory: {}", target.output_dir.display());
    println!("    Asset categories: {:?}", target.asset_categories);
    println!("    Organize by category: {}", target.organize_by_category);

    if !target.variables.is_empty() {
        println!("    Variables:");
        for (key, value) in &target.variables {
            println!("      {}={}", key, value);
        }
    }

    if let Some(ref hooks) = target.hooks {
        if !hooks.pre_build.is_empty() {
            println!("    Pre-build hooks: {:?}", hooks.pre_build);
        }
        if !hooks.post_assets.is_empty() {
            println!("    Post-assets hooks: {:?}", hooks.post_assets);
        }
        if !hooks.post_build.is_empty() {
            println!("    Post-build hooks: {:?}", hooks.post_build);
        }
        if !hooks.on_error.is_empty() {
            println!("    Error hooks: {:?}", hooks.on_error);
        }
    }
}
