//! Eval implementations for logical operators

use anyhow::bail;

use hamelin_lib::func::defs::{And, Not, Or};

use crate::registry::EvalRegistry;
use crate::value::Value;

/// Register all logical operator eval implementations.
pub fn register(registry: &mut EvalRegistry) {
    // Not: !x
    registry.register_eval::<Not>(|mut params| {
        let x = params.take()?;
        match x {
            Value::Boolean(b) => Ok(Value::Boolean(!b)),
            Value::Null => Ok(Value::Null),
            _ => bail!("Invalid operand for NOT operator"),
        }
    });

    // And: x AND y (with 3-valued logic for NULL)
    registry.register_eval::<And>(|mut params| {
        let left = params.take()?;
        let right = params.take()?;
        match (left, right) {
            (Value::Boolean(l), Value::Boolean(r)) => Ok(Value::Boolean(l && r)),
            (Value::Null, _) | (_, Value::Null) => Ok(Value::Null),
            _ => bail!("Invalid operands for AND operator"),
        }
    });

    // Or: x OR y (with 3-valued logic for NULL)
    registry.register_eval::<Or>(|mut params| {
        let left = params.take()?;
        let right = params.take()?;
        match (left, right) {
            (Value::Boolean(l), Value::Boolean(r)) => Ok(Value::Boolean(l || r)),
            (Value::Null, _) | (_, Value::Null) => Ok(Value::Null),
            _ => bail!("Invalid operands for OR operator"),
        }
    });

    // No reverse eval for logical operators - they're not typically invertible
}
