//! Pages build script - Using Provider pattern with Rustelo foundation traits
//!
//! This build script uses the Provider pattern with dependency injection
//! instead of direct function calls. Follows PAP principles completely.

mod build_page_generator;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Use new PAP-compliant manifest system
    let manifest = rustelo_utils::ManifestResolver::load()?;
    let content_path = rustelo_utils::manifest_content_path();
    let config_path = rustelo_utils::manifest_config_path();

    println!("cargo:rerun-if-changed={}", config_path.display());
    println!("cargo:rerun-if-changed=src/");
    println!("cargo:rerun-if-changed={}", content_path.display());
    println!("cargo:rerun-if-env-changed=ONTOREF_NICKEL_IMPORT_PATH");

    // Generate page components using rustelo_tools SmartCache
    build_page_generator::generate_page_components(manifest.root())?;

    // Generate content graph static maps (related_map.rs, ontology_context_map.rs,
    // graph_mini_map.rs, content_graph.json) for the content_graph page module.
    generate_content_graph(manifest.root())?;

    // Generate pages documentation using rustelo_tools
    generate_pages_documentation(&manifest)?;

    println!("cargo:warning=Pages build completed with smart caching and documentation");

    Ok(())
}

/// Run the content-graph build pipeline, writing generated files into OUT_DIR.
///
/// Requires `ONTOREF_NICKEL_IMPORT_PATH` to be set in the environment —
/// this is the only path that cannot be derived from the workspace layout.
/// All other paths default to conventional locations relative to the workspace root.
fn generate_content_graph(
    workspace_root: &std::path::Path,
) -> Result<(), Box<dyn std::error::Error>> {
    use content_graph::build::{codegen, graph_generator::GraphGeneratorConfig};

    let framework_root = workspace_root
        .join("..")
        .join("rustelo")
        .canonicalize()
        .unwrap_or_else(|_| workspace_root.join("..").join("rustelo"));

    // ONTOREF_NICKEL_IMPORT_PATH must be set externally (points to /path/to/ontoref/ontology).
    // If absent, skip graph generation gracefully so builds without ontoref still succeed.
    let ontoref_path = match std::env::var("ONTOREF_NICKEL_IMPORT_PATH") {
        Ok(p) => std::path::PathBuf::from(p),
        Err(_) => {
            println!("cargo:warning=content-graph: ONTOREF_NICKEL_IMPORT_PATH not set — skipping graph generation. Set it to enable the content graph.");
            return write_empty_graph_outputs();
        }
    };

    let config = GraphGeneratorConfig::with_root(workspace_root, &framework_root, &ontoref_path);

    println!("cargo:rerun-if-changed={}", config.content_dir.display());
    println!("cargo:rerun-if-changed={}", config.impl_ontology.display());

    match content_graph::build::graph_generator::generate(&config) {
        Ok(graph) => {
            let out_dir = std::path::PathBuf::from(std::env::var("OUT_DIR")?);
            codegen::write_outputs(&graph, &out_dir)?;
            println!(
                "cargo:warning=content-graph: generated {} nodes, {} edges",
                graph.nodes.len(),
                graph.edges.len()
            );
        }
        Err(e) => {
            println!("cargo:warning=content-graph: generation failed: {e} — writing empty outputs");
            write_empty_graph_outputs()?;
        }
    }

    Ok(())
}

/// Write empty (but valid) graph output files so the content_graph module compiles
/// even when graph generation is skipped or fails.
fn write_empty_graph_outputs() -> Result<(), Box<dyn std::error::Error>> {
    let out_dir = std::path::PathBuf::from(std::env::var("OUT_DIR")?);

    std::fs::write(
        out_dir.join("content_graph.json"),
        r#"{"nodes":[],"edges":[]}"#,
    )?;
    std::fs::write(
        out_dir.join("related_map.rs"),
        "pub struct RelatedNode { pub id: &'static str, pub title: &'static str, pub kind: &'static str, pub url: &'static str }\n\
         pub static RELATED_NODES: &[(&str, &[RelatedNode])] = &[];\n",
    )?;
    std::fs::write(
        out_dir.join("ontology_context_map.rs"),
        "pub struct OntologyRef { pub id: &'static str, pub name: &'static str, pub kind: &'static str }\n\
         pub static ONTOLOGY_CONTEXT: &[(&str, &[OntologyRef])] = &[];\n",
    )?;
    std::fs::write(
        out_dir.join("graph_mini_map.rs"),
        "pub static GRAPH_MINI_SVGS: &[(&str, &str)] = &[];\n",
    )?;

    Ok(())
}

/// Generate pages documentation using rustelo_tools comprehensive_analysis
fn generate_pages_documentation(
    manifest: &rustelo_utils::ManifestResolver,
) -> Result<(), Box<dyn std::error::Error>> {
    let project_root = manifest.root();
    let info_path = project_root.join("site").join("info");

    // Create info directory if it doesn't exist
    std::fs::create_dir_all(&info_path)?;

    // Generate pages documentation
    rustelo_tools::comprehensive_analysis::generate_pages_documentation(
        &project_root.to_string_lossy(),
        &rustelo_utils::manifest::content_path().to_string_lossy(),
        &info_path.to_string_lossy(),
    )?;

    println!("cargo:warning=Generated pages documentation in site/info");

    Ok(())
}
