//! Build command implementation

use std::collections::HashMap;
use std::path::Path;

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

/// Run the build command
pub async fn run(
    release: bool,
    no_assets: bool,
    categories: Option<Vec<String>>,
    organize_by_category: bool,
) -> Result<()> {
    tracing::info!("Building implementation...");

    // Load configurations
    let config = RusteloConfig::load().unwrap_or_default();
    let build_config = load_or_create_build_config().await?;

    // Determine build target
    let target_name = if release { "prod" } else { "dev" };

    if !no_assets {
        tracing::info!("Using build pipeline for target: {}", target_name);

        // Use enhanced build pipeline
        let pipeline = BuildPipeline::new(config, build_config);
        let result = pipeline.build_target(target_name).await?;

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

        if !result.output_files.is_empty() {
            println!("  Output files: {}", result.output_files.len());
        }
    } else {
        tracing::info!("Skipping asset processing");

        // Legacy asset processing for specific requirements
        if categories.is_some() || organize_by_category {
            process_assets(release, categories, organize_by_category).await?;
        }

        println!("✅ Build completed (no assets processed)");
    }

    // TODO: Integrate with cargo build process
    if std::path::Path::new("Cargo.toml").exists() {
        println!(
            "💡 Run `cargo build{}` to build the Rust code",
            if release { " --release" } else { "" }
        );
    }

    Ok(())
}

/// Load or create default build configuration
async fn load_or_create_build_config() -> Result<BuildConfig> {
    let config_path = "rustelo-build.toml";

    if std::path::Path::new(config_path).exists() {
        tracing::info!("Loading build configuration from: {}", config_path);
        BuildPipeline::load_build_config(config_path)
    } else {
        tracing::info!("Creating default build configuration");
        let config = BuildConfig::default();

        // Save default configuration for future use
        if let Err(e) = BuildPipeline::save_build_config(&config, config_path) {
            tracing::warn!("Failed to save build configuration: {}", e);
        } else {
            println!("📋 Created default build configuration: {}", config_path);
        }

        Ok(config)
    }
}

/// Process all assets with universal fallback resolution
async fn process_assets(
    release: bool,
    categories: Option<Vec<String>>,
    organize_by_category: bool,
) -> Result<()> {
    // Load configuration
    let config = RusteloConfig::load().unwrap_or_default();
    let resolver = AssetResolver::new(config);

    // Set up build variables
    let mut variables = HashMap::new();
    variables.insert(
        "mode".to_string(),
        if release {
            "production".to_string()
        } else {
            "development".to_string()
        },
    );
    variables.insert("timestamp".to_string(), chrono::Utc::now().to_rfc3339());

    // Determine target directory
    let target_dir = if release {
        Path::new("dist")
    } else {
        Path::new("target/debug/assets")
    };

    tracing::info!("Processing assets to: {}", target_dir.display());

    if organize_by_category {
        // Organize assets by category
        let organized = resolver.organize_by_category(target_dir, variables).await?;

        println!("✅ Asset processing completed (organized by category):");
        let mut total_files = 0;
        for (category, files) in &organized {
            println!("  📁 {:?}: {} files", category, files.len());
            total_files += files.len();
            for file in files {
                let status = if file.merged { "merged" } else { "processed" };
                tracing::debug!(
                    "    {} {} -> {} ({})",
                    status,
                    file.source_path.display(),
                    file.target_path.display(),
                    file.processor
                );
            }
        }
        println!("  Total: {} files", total_files);
    } else if let Some(category_names) = categories {
        // Parse category names
        let mut asset_categories = Vec::new();
        for name in category_names {
            match name.to_lowercase().as_str() {
                "build" => asset_categories.push(AssetCategory::Build),
                "config" => asset_categories.push(AssetCategory::Config),
                "static" => asset_categories.push(AssetCategory::Static),
                "content" => asset_categories.push(AssetCategory::Content),
                "development" | "dev" => asset_categories.push(AssetCategory::Development),
                "deployment" | "deploy" => asset_categories.push(AssetCategory::Deployment),
                _ => {
                    tracing::warn!("Unknown category: {}", name);
                    continue;
                }
            }
        }

        if asset_categories.is_empty() {
            tracing::warn!("No valid categories specified, processing all assets");
            let processed = resolver.process_assets(target_dir, variables).await?;
            println!("✅ Asset processing completed: {} files", processed.len());
        } else {
            println!("📁 Processing categories: {:?}", asset_categories);
            let processed = resolver
                .process_assets_by_category(target_dir, &asset_categories, variables)
                .await?;

            println!("✅ Asset processing completed (filtered by category):");
            println!("  {} files processed", processed.len());
            for file in &processed {
                let status = if file.merged { "merged" } else { "processed" };
                tracing::info!(
                    "  {} {} -> {} ({})",
                    status,
                    file.source_path.display(),
                    file.target_path.display(),
                    file.processor
                );
            }
        }
    } else {
        // Process all assets with fallback resolution
        let processed = resolver.process_assets(target_dir, variables).await?;

        tracing::info!("Processed {} assets:", processed.len());
        for file in &processed {
            let status = if file.merged { "merged" } else { "copied" };
            tracing::info!(
                "  {} {} -> {} ({})",
                status,
                file.source_path.display(),
                file.target_path.display(),
                file.processor
            );
        }

        println!("✅ Asset processing completed: {} files", processed.len());
    }

    Ok(())
}
