use crate::codegen::builder::RustFileBuilder;
use crate::core::config::{NodeCapsuleTypeConfig, ResolvedCrateConfig};
use crate::core::ir::ApiSurface;
use ahash::AHashSet;
use std::collections::HashMap;

pub(super) fn collect_opaque_types(
    api: &ApiSurface,
    config: &ResolvedCrateConfig,
    capsule_types: &HashMap<String, NodeCapsuleTypeConfig>,
) -> AHashSet<String> {
    let mut opaque_types: AHashSet<String> = api
        .types
        .iter()
        .filter(|t| t.is_opaque && !t.is_trait && !capsule_types.contains_key(&t.name))
        .map(|t| t.name.clone())
        .collect();

    for name in config.opaque_types.keys() {
        if !capsule_types.contains_key(name) {
            opaque_types.insert(name.clone());
        }
    }

    opaque_types
}

pub(super) fn exclude_capsule_opaque_types(
    exclude_types: &mut AHashSet<String>,
    config: &ResolvedCrateConfig,
    capsule_types: &HashMap<String, NodeCapsuleTypeConfig>,
) {
    for name in config.opaque_types.keys() {
        if capsule_types.contains_key(name) {
            exclude_types.insert(name.clone());
        }
    }
}

pub(super) fn emit_wrappers(
    builder: &mut RustFileBuilder,
    api: &ApiSurface,
    config: &ResolvedCrateConfig,
    capsule_types: &HashMap<String, NodeCapsuleTypeConfig>,
    prefix: &str,
) {
    let emitted_type_names: AHashSet<&str> = api.types.iter().map(|typ| typ.name.as_str()).collect();

    for (name, source_path) in &config.opaque_types {
        if capsule_types.contains_key(name) || emitted_type_names.contains(name.as_str()) {
            continue;
        }

        let rust_path = source_path.replace('-', "_");
        let struct_name = format!("{prefix}{name}");
        let wrapper = crate::backends::napi::template_env::render(
            "config_opaque_wrapper.rs.jinja",
            minijinja::context! {
                name => name,
                rust_path => rust_path,
                struct_name => struct_name,
            },
        );
        builder.add_item(wrapper.trim_end());
    }
}
