use std::collections::BTreeSet;
use std::fs;
use std::path::Path;

use serde::Deserialize;

use super::scan::canonicalize_building_stem;
use super::types::{BuildingTypeNamedBindingComparison, BuildingTypeSourceEntry};

#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
struct BuildingBindingArtifact {
    bindings: Vec<BuildingBindingRow>,
}

#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
struct BuildingBindingRow {
    #[serde(default)]
    candidate_name: Option<String>,
}

pub(super) fn load_named_binding_comparison(
    bindings_path: &Path,
    entries: &[BuildingTypeSourceEntry],
) -> Result<BuildingTypeNamedBindingComparison, Box<dyn std::error::Error>> {
    let artifact =
        serde_json::from_str::<BuildingBindingArtifact>(&fs::read_to_string(bindings_path)?)?;
    let named_binding_stems = artifact
        .bindings
        .into_iter()
        .filter_map(|binding| binding.candidate_name)
        .map(|candidate_name| canonicalize_building_stem(&candidate_name))
        .collect::<BTreeSet<_>>();
    let source_stems = entries
        .iter()
        .map(|entry| entry.canonical_stem.clone())
        .collect::<BTreeSet<_>>();

    Ok(BuildingTypeNamedBindingComparison {
        bindings_path: bindings_path.display().to_string(),
        named_binding_count: named_binding_stems.len(),
        shared_canonical_stem_count: named_binding_stems.intersection(&source_stems).count(),
        binding_only_canonical_stems: named_binding_stems
            .difference(&source_stems)
            .cloned()
            .collect(),
        source_only_canonical_stems: source_stems
            .difference(&named_binding_stems)
            .cloned()
            .collect(),
    })
}
