//! Route configuration loading functionality

use super::deletion::handle_page_deletion;
use super::types::RoutesConfig;
use std::fs;
use std::path::Path;

/// Load routes configuration from SITE_CONFIG_PATH/routes/ directory or fallback to routes.toml
pub fn load_routes_config(content_root: &str) -> Result<RoutesConfig, String> {
    // Use SITE_CONFIG_PATH, resolving from SITE_ROOT if needed.
    // If SITE_CONFIG_PATH points to a file (e.g. site/config/index.ncl), use its
    // parent directory as the config root, since this loader expects a directory.
    let site_config_path = std::env::var("SITE_CONFIG_PATH").unwrap_or_else(|_| {
        let site_root = std::env::var("SITE_ROOT_PATH").unwrap_or_else(|_| "site".to_string());
        format!("{}/config", site_root)
    });

    let config_dir = {
        let p = Path::new(&site_config_path);
        if p.is_file() || p.extension().is_some() {
            p.parent().unwrap_or(p).to_path_buf()
        } else {
            p.to_path_buf()
        }
    };

    let routes_dir = if config_dir.is_absolute() {
        config_dir.join("routes")
    } else if let Ok(manifest_dir) = std::env::var("CARGO_MANIFEST_DIR") {
        let project_root = Path::new(&manifest_dir)
            .parent()
            .and_then(|p| p.parent())
            .unwrap_or_else(|| Path::new("."))
            .to_path_buf();
        project_root.join(&config_dir).join("routes")
    } else {
        config_dir.join("routes")
    };
    let routes_file = Path::new(content_root).join("routes.toml");

    // Try to load from SITE_CONFIG_PATH/routes/ directory first
    if routes_dir.exists() && routes_dir.is_dir() {
        println!(
            "Loading routes from directory: {} (SITE_CONFIG_PATH)",
            routes_dir.display()
        );
        return load_routes_from_directory(&routes_dir);
    }

    // Fallback to single routes.toml file in content_root (legacy)
    if routes_file.exists() {
        println!("Loading routes from legacy file: {}", routes_file.display());
        return load_routes_from_file(&routes_file);
    }

    // If neither exists, return error with explicit paths
    Err(format!(
        "No routes configuration found. Expected {} directory (SITE_CONFIG_PATH/routes) or {} file (legacy)",
        routes_dir.display(),
        routes_file.display()
    ))
}

/// Load routes from SITE_CONFIG_PATH/routes/ directory (multiple TOML files)
fn load_routes_from_directory(routes_dir: &Path) -> Result<RoutesConfig, String> {
    let mut all_routes = Vec::new();

    // Read all .toml files in the routes directory
    let entries = fs::read_dir(routes_dir).map_err(|e| {
        format!(
            "Failed to read routes directory {}: {}",
            routes_dir.display(),
            e
        )
    })?;

    for entry in entries {
        let entry = entry.map_err(|e| format!("Failed to read directory entry: {}", e))?;
        let path = entry.path();

        // Only process .toml files
        if path.is_file() && path.extension().map_or(false, |ext| ext == "toml") {
            println!("Loading routes from: {}", path.display());

            let content = fs::read_to_string(&path)
                .map_err(|e| format!("Failed to read {}: {}", path.display(), e))?;

            let mut section_config: RoutesConfig = toml::from_str(&content)
                .map_err(|e| format!("Failed to parse TOML in {}: {}", path.display(), e))?;

            // Apply safety defaults to all routes
            apply_safety_defaults(&mut section_config.routes)?;

            println!(
                "Loaded {} routes from {}",
                section_config.routes.len(),
                path.display()
            );
            all_routes.append(&mut section_config.routes);
        }
    }

    if all_routes.is_empty() {
        return Err("No routes found in any .toml files in the routes directory".to_string());
    }

    Ok(RoutesConfig { routes: all_routes })
}

/// Load routes from single routes.toml file
fn load_routes_from_file(routes_file: &Path) -> Result<RoutesConfig, String> {
    let content = fs::read_to_string(routes_file)
        .map_err(|e| format!("Failed to read {}: {}", routes_file.display(), e))?;

    let mut routes_config: RoutesConfig = toml::from_str(&content)
        .map_err(|e| format!("Failed to parse TOML in {}: {}", routes_file.display(), e))?;

    // Apply safety defaults to all routes
    apply_safety_defaults(&mut routes_config.routes)?;

    Ok(routes_config)
}

/// Apply safety defaults to prevent accidental overwrites
pub fn apply_safety_defaults(routes: &mut Vec<super::types::Route>) -> Result<(), String> {
    use super::utils::get_module_name_from_page_component_with_route;

    for route in routes {
        // Set safety defaults if not explicitly configured
        if route.replace_existing_boilerplate.is_none() {
            route.replace_existing_boilerplate = Some(false);
        }
        if route.scaffold_template.is_none() {
            route.scaffold_template = Some(String::new());
        }
        if route.generate_boilerplate_only.is_none() {
            route.generate_boilerplate_only = Some(false);
        }
        if route.delete_existing_page.is_none() {
            route.delete_existing_page = Some(false);
        }

        // Handle page deletion if enabled - DANGEROUS operation
        if route.delete_existing_page.unwrap_or(false) {
            handle_page_deletion(route)?;
        }

        // Skip generation entirely if page directory exists
        if route.auto_scaffold.unwrap_or(false) || route.generate_boilerplate_only.unwrap_or(false)
        {
            let default_page_component = format!("{}Page", route.component);
            let page_component = route
                .page_component
                .as_ref()
                .unwrap_or(&default_page_component);
            let module_name = get_module_name_from_page_component_with_route(route);

            // Get project root from CARGO_MANIFEST_DIR
            if let Ok(manifest_dir) = std::env::var("CARGO_MANIFEST_DIR") {
                let project_root = std::path::Path::new(&manifest_dir)
                    .parent()
                    .and_then(|p| p.parent())
                    .unwrap_or_else(|| std::path::Path::new("."));
                let page_dir = project_root.join("crates/pages/src").join(&module_name);

                if page_dir.exists() {
                    println!("cargo:warning=Safety check: Skipping {} generation - directory {} already exists",
                            page_component, page_dir.display());
                    // Disable auto-scaffolding and boilerplate generation
                    route.auto_scaffold = Some(false);
                    route.generate_boilerplate_only = Some(false);
                }
            }
        }
    }
    Ok(())
}
