/// Example showing proper build.rs integration with core-lib foundation
///
/// This demonstrates how to use core-lib build utilities in your project's
/// build.rs file to generate components from TOML configuration.
///
/// This file would typically be your project's build.rs

use std::env;
use std::path::Path;

/// Main build script showing core-lib integration patterns
///
/// This demonstrates the complete build-time generation workflow:
/// 1. Configuration validation
/// 2. Foundation resource generation
/// 3. Custom extension generation (when needed)
/// 4. Integration and optimization
fn main() -> Result<(), Box<dyn std::error::Error>> {
    println!("🏗️  Rustelo Build System Integration Example");
    println!("===========================================");
    println!();

    // Step 1: Environment and configuration validation
    validate_build_environment()?;

    // Step 2: Generate foundation resources from TOML configuration
    generate_foundation_resources()?;

    // Step 3: Generate custom extensions (10% case)
    generate_custom_components_if_needed()?;

    // Step 4: Build optimization and caching
    optimize_build_output()?;

    // Step 5: Development vs production configuration
    configure_build_mode()?;

    println!("✅ Build system integration complete!");
    Ok(())
}

/// Step 1: Validate build environment and configuration files
fn validate_build_environment() -> Result<(), Box<dyn std::error::Error>> {
    println!("🔍 Step 1: Build Environment Validation");
    println!("======================================");

    // Check for required environment variables
    let manifest_dir = env::var("CARGO_MANIFEST_DIR")
        .map_err(|_| "CARGO_MANIFEST_DIR not set - not running in Cargo build")?;
    let out_dir = env::var("OUT_DIR")
        .map_err(|_| "OUT_DIR not set - not running in Cargo build")?;

    println!("✅ Build environment:");
    println!("   Manifest dir: {}", manifest_dir);
    println!("   Output dir: {}", out_dir);

    // Validate project structure
    let project_root = Path::new(&manifest_dir);
    validate_project_structure(project_root)?;

    // Check configuration files
    validate_configuration_files(project_root)?;

    Ok(())
}

fn validate_project_structure(project_root: &Path) -> Result<(), Box<dyn std::error::Error>> {
    println!("\n📁 Project structure validation:");

    let required_dirs = vec![
        ("site/config/routes", "Route configuration directory"),
        ("content/locales", "i18n locales directory"),
        ("content", "Content root directory"),
    ];

    let mut warnings = Vec::new();

    for (dir_path, description) in required_dirs {
        let dir = project_root.join(dir_path);
        if dir.exists() {
            println!("   ✅ {} - {}", dir_path, description);
        } else {
            let warning = format!("   ⚠️  {} - {} (missing, using fallbacks)", dir_path, description);
            println!("{}", warning);
            warnings.push(warning);
        }
    }

    if !warnings.is_empty() {
        println!("\n💡 Missing directories will use fallback generation");
        println!("   To enable full features, create the missing directories");
    }

    Ok(())
}

fn validate_configuration_files(project_root: &Path) -> Result<(), Box<dyn std::error::Error>> {
    println!("\n📄 Configuration file validation:");

    let config_files = vec![
        ("site/config/routes/en.toml", "English routes", true),
        ("content/content-kinds.toml", "Content types", true),
        ("config/design-system.toml", "Design system", false),
        ("site/config/features.toml", "Feature configuration", false),
    ];

    for (file_path, description, required) in config_files {
        let file = project_root.join(file_path);
        if file.exists() {
            println!("   ✅ {} - {}", file_path, description);

            // Validate TOML syntax
            match std::fs::read_to_string(&file) {
                Ok(content) => {
                    match toml::from_str::<toml::Value>(&content) {
                        Ok(_) => println!("      Valid TOML syntax"),
                        Err(e) => {
                            let error = format!("      ❌ Invalid TOML syntax: {}", e);
                            println!("{}", error);
                            if required {
                                return Err(error.into());
                            }
                        }
                    }
                }
                Err(e) => println!("      ⚠️  Could not read file: {}", e),
            }
        } else {
            if required {
                let error = format!("   ❌ {} - {} (required)", file_path, description);
                println!("{}", error);
                return Err(error.into());
            } else {
                println!("   ⚪ {} - {} (optional, not found)", file_path, description);
            }
        }
    }

    Ok(())
}

/// Step 2: Generate foundation resources using core-lib build utilities
fn generate_foundation_resources() -> Result<(), Box<dyn std::error::Error>> {
    println!("\n🏭 Step 2: Foundation Resource Generation");
    println!("========================================");

    // Check if we should skip generation (e.g., in fast dev builds)
    if env::var("SKIP_SHARED_RESOURCES_BUILD").is_ok() {
        println!("⏭️  Skipping resource generation (SKIP_SHARED_RESOURCES_BUILD=1)");
        return Ok(());
    }

    // Use core-lib smart caching system
    if env::var("SITE_DEVTOOLS_PATH").is_ok() {
        println!("🧠 Using smart cache system...");

        // In real build.rs, you would call:
        // let built = rustelo_core_lib::build::generate_shared_resources_with_cache()?;

        // For demo, simulate the caching system
        let cache_status = simulate_smart_cache_check()?;

        match cache_status {
            CacheStatus::Fresh => {
                println!("   ⚡ All resources fresh in cache - using cached version");
                println!("   📋 Generated components available from cache");
            }
            CacheStatus::Stale => {
                println!("   🔄 Cache stale - regenerating resources");
                simulate_resource_generation()?;
                println!("   💾 Updated cache with new resources");
            }
            CacheStatus::Missing => {
                println!("   🆕 No cache found - generating fresh resources");
                simulate_resource_generation()?;
                println!("   💾 Created new cache");
            }
        }
    } else {
        println!("🔨 Direct generation (no cache available)...");

        // In real build.rs, you would call:
        // rustelo_core_lib::build::generate_shared_resources()?;

        simulate_resource_generation()?;
    }

    println!("✅ Foundation resources generated");
    Ok(())
}

#[derive(Debug)]
enum CacheStatus {
    Fresh,
    Stale,
    Missing,
}

fn simulate_smart_cache_check() -> Result<CacheStatus, Box<dyn std::error::Error>> {
    println!("   🔍 Checking cache status...");

    // Simulate cache check logic
    let cache_files = vec![
        "generated_routes.rs",
        "generated_components.rs",
        "content_kinds_generated.rs",
        "resource_registry.rs",
    ];

    println!("   📁 Cache files to check:");
    for file in &cache_files {
        println!("      - {}", file);
    }

    // For demo, randomly return a status
    use std::collections::hash_map::DefaultHasher;
    use std::hash::{Hash, Hasher};

    let mut hasher = DefaultHasher::new();
    env::var("CARGO_MANIFEST_DIR").unwrap_or_default().hash(&mut hasher);
    let hash = hasher.finish();

    match hash % 3 {
        0 => Ok(CacheStatus::Fresh),
        1 => Ok(CacheStatus::Stale),
        _ => Ok(CacheStatus::Missing),
    }
}

fn simulate_resource_generation() -> Result<(), Box<dyn std::error::Error>> {
    println!("   🔨 Generating resources from configuration...");

    let generated_files = vec![
        ("generated_routes.rs", "RouteComponent enum from site/config/routes/*.toml"),
        ("generated_components.rs", "Page components with i18n from route config"),
        ("content_kinds_generated.rs", "Content type handlers from content-kinds.toml"),
        ("resource_registry.rs", "Resource mappings and utilities"),
        ("config_constants.rs", "Environment-based configuration constants"),
    ];

    for (file, description) in generated_files {
        println!("      ✅ {} - {}", file, description);

        // In real build.rs, this would be actual code generation
        // let content = generate_file_content(file)?;
        // let out_path = Path::new(&env::var("OUT_DIR")?).join(file);
        // std::fs::write(out_path, content)?;
    }

    println!("   📊 Generation statistics:");
    println!("      - Routes processed: 12");
    println!("      - Components generated: 8");
    println!("      - Content types: 4");
    println!("      - Languages detected: 3");

    Ok(())
}

/// Step 3: Generate custom components when configuration isn't enough (10% case)
fn generate_custom_components_if_needed() -> Result<(), Box<dyn std::error::Error>> {
    println!("\n🛠️  Step 3: Custom Component Generation (When Needed)");
    println!("====================================================");

    // Check if custom components are needed
    let manifest_dir = env::var("CARGO_MANIFEST_DIR")?;
    let custom_templates_dir = Path::new(&manifest_dir).join("build_templates");

    if !custom_templates_dir.exists() {
        println!("⚪ No custom templates found - using foundation components only");
        println!("   💡 To add custom components, create build_templates/ directory");
        return Ok(());
    }

    println!("🔍 Custom templates directory found: {}", custom_templates_dir.display());

    // Scan for custom template files
    let template_files = std::fs::read_dir(&custom_templates_dir)?
        .filter_map(|entry| {
            let entry = entry.ok()?;
            let path = entry.path();
            if path.extension()?.to_str()? == "rs" {
                Some(path)
            } else {
                None
            }
        })
        .collect::<Vec<_>>();

    if template_files.is_empty() {
        println!("⚪ No custom template files found in build_templates/");
        return Ok(());
    }

    println!("🎨 Generating custom components:");
    for template_file in &template_files {
        let template_name = template_file
            .file_stem()
            .unwrap()
            .to_str()
            .unwrap();

        println!("   🔨 Processing template: {}", template_name);

        // In real build.rs, you would:
        // 1. Read the template file
        // 2. Process any template variables
        // 3. Generate the final component code
        // 4. Write to OUT_DIR

        let template_content = std::fs::read_to_string(template_file)?;
        println!("      📄 Template size: {} bytes", template_content.len());

        let output_file = format!("custom_{}.rs", template_name);
        println!("      ✅ Generated: {}", output_file);

        // let processed_content = process_template_variables(template_content)?;
        // let out_path = Path::new(&env::var("OUT_DIR")?).join(output_file);
        // std::fs::write(out_path, processed_content)?;
    }

    println!("✅ Custom components generated from templates");
    Ok(())
}

/// Step 4: Build optimization and output management
fn optimize_build_output() -> Result<(), Box<dyn std::error::Error>> {
    println!("\n⚡ Step 4: Build Optimization");
    println!("============================");

    // Conditional compilation flags
    println!("🏗️  Setting conditional compilation flags:");
    if env::var("CARGO_MANIFEST_DIR").unwrap().contains("foundation") {
        println!("cargo:rustc-cfg=foundation_build");
        println!("   ✅ Foundation build mode enabled");
    }

    // Check if generated resources are available
    let out_dir = env::var("OUT_DIR")?;
    let generated_routes = Path::new(&out_dir).join("generated_routes.rs");

    if generated_routes.exists() {
        println!("cargo:rustc-cfg=has_generated_resources");
        println!("   ✅ Generated resources available");
    } else {
        println!("   ⚠️  Generated resources not found - using fallbacks");
    }

    // Build-time environment variables
    println!("\n📝 Setting build-time environment variables:");
    println!("cargo:rustc-env=BUILD_TIMESTAMP={}", chrono::Utc::now().to_rfc3339());

    if let Ok(output) = std::process::Command::new("git")
        .args(&["rev-parse", "--short", "HEAD"])
        .output()
    {
        let commit = String::from_utf8_lossy(&output.stdout).trim().to_string();
        println!("cargo:rustc-env=GIT_COMMIT={}", commit);
        println!("   ✅ Git commit: {}", commit);
    }

    // Rerun conditions
    println!("\n🔄 Setting rebuild conditions:");
    let rebuild_paths = vec![
        "site/config/routes",
        "content/content-kinds.toml",
        "content/locales",
        "build_templates",
    ];

    for path in rebuild_paths {
        println!("cargo:rerun-if-changed={}", path);
        println!("   👁️  Watching: {}", path);
    }

    Ok(())
}

/// Step 5: Configure build mode (development vs production)
fn configure_build_mode() -> Result<(), Box<dyn std::error::Error>> {
    println!("\n🎛️  Step 5: Build Mode Configuration");
    println!("===================================");

    let profile = env::var("PROFILE").unwrap_or("debug".to_string());
    let is_release = profile == "release";

    println!("🏷️  Build profile: {}", profile);

    if is_release {
        println!("🚀 Production build configuration:");
        println!("   ✅ Optimized component generation");
        println!("   ✅ Minified output");
        println!("   ✅ Cache optimization enabled");
        println!("   ⚠️  Debug features disabled");

        // Production optimizations
        println!("cargo:rustc-cfg=production_build");

    } else {
        println!("🛠️  Development build configuration:");
        println!("   ✅ Debug information included");
        println!("   ✅ Hot reload support");
        println!("   ✅ Detailed error messages");
        println!("   ✅ Build-time validation");

        // Development features
        println!("cargo:rustc-cfg=development_build");

        // Enable debug features
        if env::var("RUSTELO_DEBUG").is_ok() {
            println!("cargo:rustc-cfg=rustelo_debug");
            println!("   🐛 Debug mode enabled");
        }
    }

    // Feature-specific configuration
    configure_features(&profile)?;

    Ok(())
}

fn configure_features(profile: &str) -> Result<(), Box<dyn std::error::Error>> {
    println!("\n🎛️  Feature configuration:");

    // Read Cargo.toml to see what features are enabled
    let manifest_dir = env::var("CARGO_MANIFEST_DIR")?;
    let cargo_toml_path = Path::new(&manifest_dir).join("Cargo.toml");

    if cargo_toml_path.exists() {
        let cargo_content = std::fs::read_to_string(cargo_toml_path)?;

        // Simple feature detection (in real build.rs, use cargo_toml crate)
        let features_enabled = vec![
            ("ssr", cargo_content.contains("ssr")),
            ("content-static", cargo_content.contains("content-static")),
            ("hot-reload", cargo_content.contains("hot-reload")),
            ("cache", cargo_content.contains("cache")),
        ];

        for (feature, enabled) in features_enabled {
            if enabled {
                println!("   ✅ {} feature enabled", feature);

                // Configure feature-specific build settings
                match feature {
                    "ssr" => {
                        println!("      📄 Server-side rendering enabled");
                        println!("cargo:rustc-cfg=feature_ssr");
                    }
                    "content-static" => {
                        println!("      📁 Static content processing enabled");
                        println!("cargo:rustc-cfg=feature_content_static");
                    }
                    "hot-reload" => {
                        if profile == "debug" {
                            println!("      🔥 Hot reload enabled (debug build)");
                            println!("cargo:rustc-cfg=feature_hot_reload");
                        }
                    }
                    "cache" => {
                        println!("      💾 Caching system enabled");
                        println!("cargo:rustc-cfg=feature_cache");
                    }
                    _ => {}
                }
            } else {
                println!("   ⚪ {} feature disabled", feature);
            }
        }
    }

    Ok(())
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_build_environment_validation() {
        // Test that validation functions work
        let result = validate_build_environment();
        // Should work or fail gracefully
        assert!(result.is_ok() || result.is_err());
    }

    #[test]
    fn test_cache_status_simulation() {
        let result = simulate_smart_cache_check();
        assert!(result.is_ok(), "Cache status check should not panic");

        let status = result.unwrap();
        match status {
            CacheStatus::Fresh | CacheStatus::Stale | CacheStatus::Missing => {
                // All variants are valid
            }
        }
    }

    #[test]
    fn test_resource_generation_simulation() {
        let result = simulate_resource_generation();
        assert!(result.is_ok(), "Resource generation simulation should not panic");
    }
}

// Demo helper functions
impl std::fmt::Display for CacheStatus {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            CacheStatus::Fresh => write!(f, "Fresh"),
            CacheStatus::Stale => write!(f, "Stale"),
            CacheStatus::Missing => write!(f, "Missing"),
        }
    }
}

// Mock chrono for the example (in real build.rs you'd use chrono crate)
mod chrono {
    pub struct Utc;

    impl Utc {
        pub fn now() -> DateTime {
            DateTime
        }
    }

    pub struct DateTime;

    impl DateTime {
        pub fn to_rfc3339(&self) -> String {
            "2024-01-01T12:00:00Z".to_string()
        }
    }
}

// Mock toml for the example (in real build.rs you'd use toml crate)
mod toml {
    use std::collections::HashMap;

    pub type Value = HashMap<String, String>;

    pub fn from_str<T>(_content: &str) -> Result<T, &'static str> {
        Err("Mock TOML parser")
    }
}
