//! Enhanced Page Scaffolding with Virtual Resolution
//!
//! This module integrates the virtual resolution system into page scaffolding,
//! enabling the use of foundation pages and components without local cloning.

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

use chrono::Utc;

use crate::build::virtual_resolution::{ResolvedItemType, VirtualResolver};

/// Enhanced page scaffolding entry point using virtual resolution
pub fn run_enhanced_page_scaffolding(
    project_root: &Path,
) -> Result<usize, Box<dyn std::error::Error>> {
    // Only run scaffolding in development mode for safety
    if !is_development_mode() {
        println!("cargo:warning=Enhanced page scaffolding skipped - not in development mode");
        return Ok(0);
    }

    println!("cargo:warning=Running enhanced page scaffolding with virtual resolution");

    // Initialize virtual resolver
    let resolver = VirtualResolver::new()?;

    // Use PAP-compliant path resolution
    let manifest = crate::build::path_resolution::get_manifest_resolver()?;
    let routes_path = manifest.get_path("routes")?;
    let pages_src_dir = project_root.join("crates/pages/src");
    let i18n_path = manifest.get_path("i18n")?;

    if !routes_path.exists() {
        println!(
            "cargo:warning=No routes directory found at: {}",
            routes_path.display()
        );
        return Ok(0); // No routes to process
    }

    let mut total_changes = 0;

    // Process all .toml files in routes directory
    for entry in std::fs::read_dir(&routes_path)? {
        let entry = entry?;
        let path = entry.path();

        if path.extension().and_then(|s| s.to_str()) == Some("toml") {
            let changes =
                process_route_file_enhanced(&path, &resolver, &pages_src_dir, &i18n_path)?;
            total_changes += changes;
        }
    }

    println!(
        "cargo:warning=Enhanced page scaffolding completed with {} changes",
        total_changes
    );
    Ok(total_changes)
}

/// Process a route file using virtual resolution
fn process_route_file_enhanced(
    route_file: &Path,
    resolver: &VirtualResolver,
    _pages_src_dir: &Path,
    i18n_path: &Path,
) -> Result<usize, Box<dyn std::error::Error>> {
    use std::fs;

    let content = fs::read_to_string(route_file)?;
    let mut config: toml::Value = toml::from_str(&content)?;
    let mut changes = 0;
    let mut config_changed = false;

    if let Some(routes) = config.get_mut("routes").and_then(|v| v.as_array_mut()) {
        for route_value in routes {
            if let Some(route) = route_value.as_table_mut() {
                let component = route
                    .get("component")
                    .and_then(|v| v.as_str())
                    .unwrap_or_default()
                    .to_string();

                if component.is_empty() {
                    continue;
                }

                let page_name = component_to_page_name(&component);

                // Use virtual resolution to find or create the page
                match resolver.resolve_page(&page_name) {
                    Ok(resolution) => {
                        println!(
                            "cargo:warning=Resolved page '{}' using {:?} from {:?}",
                            page_name,
                            resolution.item.source,
                            resolution
                                .resolution_path
                                .last()
                                .map(|s| &s.source)
                                .unwrap_or(&resolution.item.source)
                        );

                        // Apply the resolution (generate files if needed)
                        if resolution.needs_generation {
                            if let Err(e) = resolver.apply_resolution(&resolution) {
                                println!(
                                    "cargo:warning=Failed to apply resolution for '{}': {}",
                                    page_name, e
                                );
                                continue;
                            }
                            changes += 1;
                        }

                        // Update route configuration based on resolution
                        update_route_after_resolution(route, &resolution);
                        config_changed = true;

                        // Generate i18n files if needed
                        if let Some(title) = route.get("title").and_then(|v| v.as_str()) {
                            if let Err(e) = ensure_i18n_entries(i18n_path, &page_name, title) {
                                println!(
                                    "cargo:warning=Failed to generate i18n entries for '{}': {}",
                                    page_name, e
                                );
                            }
                        }
                    }
                    Err(e) => {
                        println!(
                            "cargo:warning=Failed to resolve page '{}': {}",
                            page_name, e
                        );
                        continue;
                    }
                }
            }
        }
    }

    // Write back the updated configuration if it changed
    if config_changed {
        let updated_content = format!(
            "# Auto-updated by enhanced build system at {}\n# Virtual resolution applied for \
             missing pages\n\n{}",
            Utc::now().format("%Y-%m-%d %H:%M:%S UTC"),
            toml::to_string_pretty(&config)?
        );
        fs::write(route_file, updated_content)?;
        println!(
            "cargo:warning=Updated route configuration: {}",
            route_file.display()
        );
    }

    Ok(changes)
}

/// Update route configuration after virtual resolution
fn update_route_after_resolution(
    route: &mut toml::value::Table,
    resolution: &crate::build::virtual_resolution::VirtualResolution,
) {
    use crate::build::virtual_resolution::ResolutionSource;

    match resolution.item.source {
        ResolutionSource::Local => {
            // Page already exists locally, disable all generation
            route.insert("auto_scaffold".to_string(), toml::Value::Boolean(false));
            route.insert(
                "generate_boilerplate_only".to_string(),
                toml::Value::Boolean(false),
            );
            route.insert("auto_generate".to_string(), toml::Value::Boolean(false));
            route.insert(
                "resolution_source".to_string(),
                toml::Value::String("local".to_string()),
            );
        }
        ResolutionSource::Foundation => {
            // Using foundation item, mark as resolved
            route.insert("auto_scaffold".to_string(), toml::Value::Boolean(false));
            route.insert(
                "generate_boilerplate_only".to_string(),
                toml::Value::Boolean(false),
            );
            route.insert("auto_generate".to_string(), toml::Value::Boolean(false));
            route.insert(
                "resolution_source".to_string(),
                toml::Value::String("foundation".to_string()),
            );
            route.insert(
                "foundation_item".to_string(),
                toml::Value::String(resolution.item.name.clone()),
            );
        }
        ResolutionSource::LocalOverride => {
            // Using local override, mark as resolved
            route.insert("auto_scaffold".to_string(), toml::Value::Boolean(false));
            route.insert(
                "resolution_source".to_string(),
                toml::Value::String("local_override".to_string()),
            );
        }
        ResolutionSource::Generated => {
            // Generated boilerplate, mark as scaffolded
            route.insert("auto_scaffold".to_string(), toml::Value::Boolean(false));
            route.insert(
                "generate_boilerplate_only".to_string(),
                toml::Value::Boolean(false),
            );
            route.insert(
                "resolution_source".to_string(),
                toml::Value::String("generated".to_string()),
            );
        }
        ResolutionSource::FeatureOverride(_) => {
            // Using feature override, mark as resolved
            route.insert("auto_scaffold".to_string(), toml::Value::Boolean(false));
            route.insert(
                "resolution_source".to_string(),
                toml::Value::String("feature_override".to_string()),
            );
        }
    }

    // Add resolution metadata for debugging/tracing
    let resolution_steps: Vec<toml::Value> = resolution
        .resolution_path
        .iter()
        .map(|step| {
            let mut step_table = toml::value::Table::new();
            step_table.insert(
                "source".to_string(),
                toml::Value::String(format!("{:?}", step.source)),
            );
            step_table.insert("found".to_string(), toml::Value::Boolean(step.found));
            step_table.insert(
                "reason".to_string(),
                toml::Value::String(step.reason.clone()),
            );
            toml::Value::Table(step_table)
        })
        .collect();

    route.insert(
        "resolution_trace".to_string(),
        toml::Value::Array(resolution_steps),
    );
}

/// Ensure i18n entries exist for a page
fn ensure_i18n_entries(
    i18n_path: &Path,
    page_name: &str,
    title: &str,
) -> Result<(), Box<dyn std::error::Error>> {
    use std::fs;

    // Get available language directories
    if !i18n_path.exists() {
        return Ok(()); // No i18n setup
    }

    for entry in fs::read_dir(i18n_path)? {
        let entry = entry?;
        let lang_dir = entry.path();

        if lang_dir.is_dir() {
            let lang_code = lang_dir
                .file_name()
                .and_then(|n| n.to_str())
                .unwrap_or("unknown");

            let pages_ftl = lang_dir.join("pages.ftl");

            // Generate or update the pages.ftl file
            let page_key = page_name.to_lowercase().replace("page", "");
            let page_entries = format!(
                "\n# {} page entries\n{}-title = {}\n{}-description = Description for {} page\n",
                page_name, page_key, title, page_key, page_name
            );

            if pages_ftl.exists() {
                // Check if entries already exist
                let content = fs::read_to_string(&pages_ftl)?;
                if !content.contains(&format!("{}-title", page_key)) {
                    // Append new entries
                    let mut updated_content = content;
                    if !updated_content.ends_with('\n') {
                        updated_content.push('\n');
                    }
                    updated_content.push_str(&page_entries);
                    fs::write(&pages_ftl, updated_content)?;

                    println!(
                        "cargo:warning=Added i18n entries for '{}' in {}",
                        page_name,
                        pages_ftl.display()
                    );
                }
            } else {
                // Create new pages.ftl file
                let initial_content = format!(
                    "# Pages i18n entries for {} language\n# Generated by enhanced page \
                     scaffolding\n{}",
                    lang_code, page_entries
                );
                fs::write(&pages_ftl, initial_content)?;

                println!(
                    "cargo:warning=Created i18n file with '{}' entries: {}",
                    page_name,
                    pages_ftl.display()
                );
            }
        }
    }

    Ok(())
}

/// Convert component name to page name (same as original for compatibility)
fn component_to_page_name(component: &str) -> String {
    // Remove "Page" suffix if present and convert to proper case
    let name = if let Some(stripped) = component.strip_suffix("Page") {
        stripped
    } else {
        component
    };

    // Ensure first letter is uppercase
    let mut chars: Vec<char> = name.chars().collect();
    if let Some(first) = chars.first_mut() {
        *first = first.to_uppercase().next().unwrap();
    }

    chars.into_iter().collect()
}

/// Check if we're running in development mode (same as original)
fn is_development_mode() -> bool {
    let env_check = env::var("ENVIRONMENT")
        .map(|e| e == "development" || e == "dev")
        .unwrap_or(false);

    let profile_check = env::var("PROFILE").map(|p| p == "debug").unwrap_or(false);
    let cargo_check = cfg!(debug_assertions);
    let has_env_file = Path::new(".env").exists() || Path::new("../../.env").exists();

    env_check || profile_check || cargo_check || has_env_file
}

/// Integration function to try enhanced scaffolding first, fallback to original
pub fn run_page_scaffolding_with_virtual_resolution(
    project_root: &Path,
) -> Result<usize, Box<dyn std::error::Error>> {
    // Try enhanced scaffolding first
    match run_enhanced_page_scaffolding(project_root) {
        Ok(changes) => {
            if changes > 0 {
                println!(
                    "cargo:warning=Enhanced page scaffolding succeeded with {} changes",
                    changes
                );
            }
            Ok(changes)
        }
        Err(e) => {
            println!(
                "cargo:warning=Enhanced page scaffolding failed: {}, falling back to basic \
                 scaffolding",
                e
            );
            // Fallback to original scaffolding
            crate::build::page_scaffolding::run_page_scaffolding(project_root)
        }
    }
}
