//! Field profiler: discovers identity signals from data and bootstraps an IdentityPlan.
//!
//! This is the Rust equivalent of the Python SDK's `_profiler.py`. It scans
//! `external_entities.raw_data` keys, detects identity signals (email, phone,
//! name, company), computes uniqueness/null rates, and builds a compiled
//! `IdentityPlan` ready for the `ReconciliationEngine`.

pub mod signals;
pub mod catalogs;
pub mod profile;
pub mod blocking;
pub mod planning;
pub mod analysis;

// Re-export all public items so that `cannon_common::field_profiler::X` continues
// to work for all existing consumers. Zero breaking changes.
pub use signals::*;
pub use catalogs::*;
pub use profile::*;
pub use blocking::*;
pub use planning::*;
pub use analysis::*;

#[cfg(test)]
mod tests {
    // Cross-module integration tests that exercise the full pipeline.
    use super::*;

    #[test]
    fn test_per_source_field_mappings_cross_source() {
        let rows: Vec<(serde_json::Value, String)> = vec![
            (serde_json::json!({"product_name": "MacBook Air", "sku": "STR-001", "brand": "Apple", "category": "Laptops"}), "store".into()),
            (serde_json::json!({"product_name": "Galaxy S24", "sku": "STR-002", "brand": "Samsung", "category": "Phones"}), "store".into()),
            (serde_json::json!({"item_name": "MACBOOK AIR", "supplier_sku": "RE123", "manufacturer": "Apple", "product_category": "LAPTOPS"}), "supplier".into()),
            (serde_json::json!({"item_name": "GALAXY S24", "supplier_sku": "GN456", "manufacturer": "Samsung", "product_category": "PHONES"}), "supplier".into()),
        ];

        let profile = profile_from_rows_with_entity(
            uuid::Uuid::nil(),
            &rows,
            Some(EntityType::Product),
        );

        let store_cols = profile.source_columns.get("store").unwrap();
        assert!(store_cols.contains("product_name"));
        assert!(store_cols.contains("sku"));
        let supplier_cols = profile.source_columns.get("supplier").unwrap();
        assert!(supplier_cols.contains("item_name"));
        assert!(supplier_cols.contains("supplier_sku"));

        let plan = build_identity_plan_with_entity(
            &profile,
            &["store".to_string(), "supplier".to_string()],
            "v1",
            "product",
            None,
        );

        let store_src = plan.sources.iter().find(|s| s.name == "store").unwrap();
        let supplier_src = plan.sources.iter().find(|s| s.name == "supplier").unwrap();

        assert_eq!(store_src.field_mappings.get("product_name"), Some(&"product_name".to_string()));
        assert_eq!(store_src.field_mappings.get("sku"), Some(&"sku".to_string()));
        assert_eq!(store_src.field_mappings.get("brand"), Some(&"brand".to_string()));
        assert_eq!(store_src.field_mappings.get("category"), Some(&"category".to_string()));

        assert_eq!(supplier_src.field_mappings.get("product_name"), Some(&"item_name".to_string()));
        assert_eq!(supplier_src.field_mappings.get("sku"), Some(&"supplier_sku".to_string()));
        assert_eq!(supplier_src.field_mappings.get("brand"), Some(&"manufacturer".to_string()));
        assert_eq!(supplier_src.field_mappings.get("category"), Some(&"product_category".to_string()));
    }
}
