use std::collections::BTreeSet;

use super::types::{
    CargoLiveRegistryEntry, CargoRegistrySourceKind, CargoSkinDescriptorEntry, CargoTypeEntry,
};

pub(super) fn build_live_registry_entries(
    cargo_type_entries: &[CargoTypeEntry],
    cargo_skin_entries: &[CargoSkinDescriptorEntry],
) -> Vec<CargoLiveRegistryEntry> {
    let mut visible_names = cargo_type_entries
        .iter()
        .map(|entry| entry.name.visible_name.clone())
        .chain(
            cargo_skin_entries
                .iter()
                .map(|entry| entry.name.visible_name.clone()),
        )
        .collect::<BTreeSet<_>>()
        .into_iter()
        .collect::<Vec<_>>();
    visible_names.sort();

    visible_names
        .into_iter()
        .map(|visible_name| {
            let mut raw_names = cargo_type_entries
                .iter()
                .filter(|entry| entry.name.visible_name == visible_name)
                .map(|entry| entry.name.raw_name.clone())
                .chain(
                    cargo_skin_entries
                        .iter()
                        .filter(|entry| entry.name.visible_name == visible_name)
                        .map(|entry| entry.name.raw_name.clone()),
                )
                .collect::<BTreeSet<_>>()
                .into_iter()
                .collect::<Vec<_>>();
            raw_names.sort();

            let localized_string_ids = cargo_type_entries
                .iter()
                .filter(|entry| entry.name.visible_name == visible_name)
                .filter_map(|entry| entry.name.localized_string_id)
                .chain(
                    cargo_skin_entries
                        .iter()
                        .filter(|entry| entry.name.visible_name == visible_name)
                        .filter_map(|entry| entry.name.localized_string_id),
                )
                .collect::<BTreeSet<_>>()
                .into_iter()
                .collect::<Vec<_>>();

            let mut source_kinds = Vec::new();
            if cargo_type_entries
                .iter()
                .any(|entry| entry.name.visible_name == visible_name)
            {
                source_kinds.push(CargoRegistrySourceKind::CargoTypes);
            }
            if cargo_skin_entries
                .iter()
                .any(|entry| entry.name.visible_name == visible_name)
            {
                source_kinds.push(CargoRegistrySourceKind::CargoSkin);
            }

            CargoLiveRegistryEntry {
                visible_name,
                raw_names,
                localized_string_ids,
                source_kinds,
            }
        })
        .collect()
}
