use pyo3::prelude::*;
use crate::ReconciliationEngine;
use crate::types::NormalizedEntity;
use crate::ir::IdentityPlan;
use crate::overrides::{OverrideResolver, ManualOverride};

#[pyfunction]
fn reconcile(plan_json: &str, entities_json: &str, overrides_json: &str) -> PyResult<String> {
    let plan: IdentityPlan = serde_json::from_str(plan_json)
        .map_err(|e| PyErr::new::<pyo3::exceptions::PyValueError, _>(e.to_string()))?;
    
    let entities: Vec<NormalizedEntity> = serde_json::from_str(entities_json)
        .map_err(|e| PyErr::new::<pyo3::exceptions::PyValueError, _>(e.to_string()))?;
        
    let overrides: Vec<ManualOverride> = serde_json::from_str(overrides_json)
        .map_err(|e| PyErr::new::<pyo3::exceptions::PyValueError, _>(e.to_string()))?;

    let engine = ReconciliationEngine::from_plan(&plan);
    let resolver = OverrideResolver::new(overrides);
    
    let decisions = engine.reconcile(&entities, &resolver);
    
    serde_json::to_string(&decisions)
        .map_err(|e| PyErr::new::<pyo3::exceptions::PyRuntimeError, _>(e.to_string()))
}

#[pyfunction]
fn compile_spec(yaml_str: &str) -> PyResult<String> {
    let spec = crate::spec::IdentitySpec::from_yaml(yaml_str)
        .map_err(|e| PyErr::new::<pyo3::exceptions::PyValueError, _>(e.to_string()))?;
        
    let plan = crate::compiler::SpecCompiler::compile(&spec)
        .map_err(|e| PyErr::new::<pyo3::exceptions::PyRuntimeError, _>(e.to_string()))?;
        
    serde_json::to_string(&plan)
        .map_err(|e| PyErr::new::<pyo3::exceptions::PyRuntimeError, _>(e.to_string()))
}

#[pyfunction]
fn estimate_impact(plan_json: &str, entities_json: &str) -> PyResult<String> {
    let plan: IdentityPlan = serde_json::from_str(plan_json)
        .map_err(|e| PyErr::new::<pyo3::exceptions::PyValueError, _>(e.to_string()))?;
    
    let entities: Vec<NormalizedEntity> = serde_json::from_str(entities_json)
        .map_err(|e| PyErr::new::<pyo3::exceptions::PyValueError, _>(e.to_string()))?;

    let analysis = crate::compiler::SpecCompiler::estimate_impact(&plan, &entities);
    
    serde_json::to_string(&analysis)
        .map_err(|e| PyErr::new::<pyo3::exceptions::PyRuntimeError, _>(e.to_string()))
}

#[pymodule]
fn kanoniv_engine(m: &Bound<'_, PyModule>) -> PyResult<()> {
    m.add_function(wrap_pyfunction!(reconcile, m)?)?;
    m.add_function(wrap_pyfunction!(compile_spec, m)?)?;
    m.add_function(wrap_pyfunction!(estimate_impact, m)?)?;
    Ok(())
}
