"""
APE Standard Library - Comparison Module

Strict, type-safe comparison operators.

All comparisons in APE are:
- Deterministic (same inputs → same output)
- Type-strict (no implicit coercion)
- Explicit (errors on type mismatch)

DESIGN PRINCIPLES:
1. No type coercion - comparing int and str raises ComparisonTypeError
2. None is not comparable to anything (including None)
3. Collections compare element-wise only if same type
4. All errors are deterministic and traceable
"""

from typing import Any
from ape.std.errors import ComparisonTypeError


def _check_comparable_types(operation: str, a: Any, b: Any) -> None:
    """
    Validate that two values can be compared.
    
    Args:
        operation: Name of comparison operation
        a: First value
        b: Second value
        
    Raises:
        ComparisonTypeError: If types are not comparable
    """
    # None is not comparable
    if a is None or b is None:
        raise ComparisonTypeError(operation, type(a), type(b))
    
    # Must be same type for strict comparison
    if type(a) is not type(b):
        raise ComparisonTypeError(operation, type(a), type(b))
    
    # Must be comparable type
    if not isinstance(a, (int, float, str, bool)):
        raise ComparisonTypeError(
            operation,
            type(a),
            type(b)
        )


def eq(a: Any, b: Any) -> bool:
    """
    Strict equality comparison.
    
    Args:
        a: First value
        b: Second value
        
    Returns:
        True if a equals b, False otherwise
        
    Raises:
        ComparisonTypeError: If types are not comparable
        
    Examples:
        eq(1, 1) → True
        eq(1, 2) → False
        eq(1, 1.0) → ComparisonTypeError (different types)
        eq("hello", "hello") → True
    """
    _check_comparable_types("eq", a, b)
    return a == b


def neq(a: Any, b: Any) -> bool:
    """
    Strict inequality comparison.
    
    Args:
        a: First value
        b: Second value
        
    Returns:
        True if a not equals b, False otherwise
        
    Raises:
        ComparisonTypeError: If types are not comparable
        
    Examples:
        neq(1, 2) → True
        neq(1, 1) → False
        neq(1, 1.0) → ComparisonTypeError (different types)
    """
    _check_comparable_types("neq", a, b)
    return a != b


def lt(a: Any, b: Any) -> bool:
    """
    Strict less-than comparison.
    
    Args:
        a: First value
        b: Second value
        
    Returns:
        True if a < b, False otherwise
        
    Raises:
        ComparisonTypeError: If types are not comparable or not orderable
        
    Examples:
        lt(1, 2) → True
        lt(2, 1) → False
        lt(1, 1.0) → ComparisonTypeError (different types)
        lt(True, False) → ComparisonTypeError (booleans not orderable)
    """
    _check_comparable_types("lt", a, b)
    
    # Booleans are not orderable in APE
    if isinstance(a, bool):
        raise ComparisonTypeError("lt", bool, bool)
    
    return a < b


def lte(a: Any, b: Any) -> bool:
    """
    Strict less-than-or-equal comparison.
    
    Args:
        a: First value
        b: Second value
        
    Returns:
        True if a <= b, False otherwise
        
    Raises:
        ComparisonTypeError: If types are not comparable or not orderable
        
    Examples:
        lte(1, 2) → True
        lte(1, 1) → True
        lte(2, 1) → False
    """
    _check_comparable_types("lte", a, b)
    
    # Booleans are not orderable in APE
    if isinstance(a, bool):
        raise ComparisonTypeError("lte", bool, bool)
    
    return a <= b


def gt(a: Any, b: Any) -> bool:
    """
    Strict greater-than comparison.
    
    Args:
        a: First value
        b: Second value
        
    Returns:
        True if a > b, False otherwise
        
    Raises:
        ComparisonTypeError: If types are not comparable or not orderable
        
    Examples:
        gt(2, 1) → True
        gt(1, 2) → False
        gt(1, 1) → False
    """
    _check_comparable_types("gt", a, b)
    
    # Booleans are not orderable in APE
    if isinstance(a, bool):
        raise ComparisonTypeError("gt", bool, bool)
    
    return a > b


def gte(a: Any, b: Any) -> bool:
    """
    Strict greater-than-or-equal comparison.
    
    Args:
        a: First value
        b: Second value
        
    Returns:
        True if a >= b, False otherwise
        
    Raises:
        ComparisonTypeError: If types are not comparable or not orderable
        
    Examples:
        gte(2, 1) → True
        gte(1, 1) → True
        gte(1, 2) → False
    """
    _check_comparable_types("gte", a, b)
    
    # Booleans are not orderable in APE
    if isinstance(a, bool):
        raise ComparisonTypeError("gte", bool, bool)
    
    return a >= b


__all__ = ['eq', 'neq', 'lt', 'lte', 'gt', 'gte']
