"""
Circular Validation - System Integrity Checker
Standalone version for cubesquare package.

Validates circular system integrity.
"""

from enum import Enum
from dataclasses import dataclass
from typing import List, Optional, Dict
import time


class ValidationLevel(Enum):
    """Validation severity levels."""
    INFO = "info"
    WARNING = "warning"
    ERROR = "error"
    CRITICAL = "critical"


@dataclass
class ValidationResult:
    """Result from validation check."""
    passed: bool
    level: ValidationLevel
    message: str
    details: Optional[Dict] = None
    check_time_ms: Optional[float] = None

    def to_dict(self) -> dict:
        """Convert to JSON-serializable dict."""
        return {
            'passed': self.passed,
            'level': self.level.value,
            'message': self.message,
            'details': self.details or {},
            'check_time_ms': self.check_time_ms,
        }


class CircularValidator:
    """
    Circular system validator.

    Validation Categories:
    1. Loop Integrity - No unbounded loops
    2. State Consistency - All states valid
    3. SRL Validity - All SRL distances converge
    """

    def __init__(self):
        """Initialize validator."""
        pass

    def validate_loop(self, loop_hex_ids: List[str], max_length: int = 1000) -> ValidationResult:
        """
        Validate loop is bounded and convergent.

        Args:
            loop_hex_ids: Hex IDs in loop
            max_length: Maximum allowed loop length

        Returns:
            ValidationResult indicating if loop is valid
        """
        start_time = time.perf_counter()

        loop_length = len(loop_hex_ids)

        if loop_length > max_length:
            elapsed_ms = (time.perf_counter() - start_time) * 1000
            return ValidationResult(
                passed=False,
                level=ValidationLevel.ERROR,
                message=f"Loop exceeds max length: {loop_length} > {max_length}",
                details={'loop_length': loop_length, 'max_length': max_length},
                check_time_ms=elapsed_ms
            )

        # Check convergence
        from .state_machine import get_stability_from_loop
        dominant_state = get_stability_from_loop(loop_hex_ids)

        elapsed_ms = (time.perf_counter() - start_time) * 1000

        if dominant_state.is_stable():
            return ValidationResult(
                passed=True,
                level=ValidationLevel.INFO,
                message=f"Loop is valid and convergent (length={loop_length})",
                details={'loop_length': loop_length, 'dominant_state': dominant_state.name},
                check_time_ms=elapsed_ms
            )
        else:
            return ValidationResult(
                passed=False,
                level=ValidationLevel.WARNING,
                message=f"Loop may be unstable (state={dominant_state.name})",
                details={'loop_length': loop_length, 'dominant_state': dominant_state.name},
                check_time_ms=elapsed_ms
            )

    def validate_srl(self, distance: int, max_distance: int = 1000000) -> ValidationResult:
        """
        Validate SRL distance is convergent.

        Args:
            distance: SRL distance value
            max_distance: Maximum allowed distance

        Returns:
            ValidationResult indicating if SRL is valid
        """
        start_time = time.perf_counter()

        if distance < 0:
            elapsed_ms = (time.perf_counter() - start_time) * 1000
            return ValidationResult(
                passed=False,
                level=ValidationLevel.ERROR,
                message=f"SRL distance is negative: {distance}",
                details={'distance': distance},
                check_time_ms=elapsed_ms
            )

        if distance > max_distance:
            elapsed_ms = (time.perf_counter() - start_time) * 1000
            return ValidationResult(
                passed=False,
                level=ValidationLevel.ERROR,
                message=f"SRL distance exceeds max: {distance} > {max_distance}",
                details={'distance': distance, 'max_distance': max_distance},
                check_time_ms=elapsed_ms
            )

        from .srl_integration import srl_distance
        t = srl_distance(distance)
        reconstructed_d = t * t
        residual = distance - reconstructed_d
        max_residual = 2 * t if t > 0 else 1

        elapsed_ms = (time.perf_counter() - start_time) * 1000

        if residual > max_residual or residual < 0:
            return ValidationResult(
                passed=False,
                level=ValidationLevel.ERROR,
                message=f"SRL inconsistency: residual {residual} outside valid range",
                details={
                    'distance': distance, 't': t, 'residual': residual,
                    'max_residual': max_residual,
                },
                check_time_ms=elapsed_ms
            )

        return ValidationResult(
            passed=True,
            level=ValidationLevel.INFO,
            message=f"SRL valid: t={t}, d={distance}",
            details={'distance': distance, 't': t, 'residual': residual},
            check_time_ms=elapsed_ms
        )

    def validate_performance(self) -> List[ValidationResult]:
        """Validate system meets performance targets."""
        results = []

        # Check SRL performance
        from .srl_integration import srl_distance
        start = time.perf_counter()
        for i in range(1000):
            _ = srl_distance(i * 100)
        elapsed_ms = (time.perf_counter() - start) * 1000
        avg_ns = (elapsed_ms * 1_000_000) / 1000

        results.append(ValidationResult(
            passed=avg_ns < 100000,
            level=ValidationLevel.INFO,
            message=f"SRL performance: {avg_ns:.1f}ns per op",
            details={'avg_ns': avg_ns},
            check_time_ms=elapsed_ms
        ))

        return results

    def validate_all(self, system_state: Dict) -> List[ValidationResult]:
        """Run all validation checks on system state."""
        results = []

        for loop in system_state.get('loops', []):
            results.append(self.validate_loop(loop))

        for distance in system_state.get('srl_distances', []):
            results.append(self.validate_srl(distance))

        results.extend(self.validate_performance())

        return results
