"""
Recognizer - Validation Programs that scan for anomalies.

"Recognizers patrol The Grid, ensuring order and quality."
"""

from dataclasses import dataclass, field
from datetime import datetime
from typing import Optional, Any
from enum import Enum
import uuid

from .program import Program, ProgramType, ProgramStatus


class ValidationResult(Enum):
    """Result of a Recognizer scan."""
    VALID = "valid"           # All checks passed
    RECTIFY_NEEDED = "rectify_needed"  # Issues found, can be fixed
    DEREZ = "derez"           # Critical failure, reject


class RecognizerType(Enum):
    """Type of Recognizer."""
    CODE = "code"              # Code quality validation
    ARCHITECTURE = "architecture"  # Design validation
    SECURITY = "security"      # Security scanning
    CONSISTENCY = "consistency"  # Artifact alignment


@dataclass
class ValidationIssue:
    """An issue found during validation."""
    severity: str  # low, medium, high, critical
    category: str
    message: str
    location: Optional[str] = None
    suggestion: Optional[str] = None

    def to_dict(self) -> dict:
        return {
            "severity": self.severity,
            "category": self.category,
            "message": self.message,
            "location": self.location,
            "suggestion": self.suggestion,
        }


@dataclass
class ScanResult:
    """Result of a Recognizer scan."""
    result: ValidationResult
    issues: list[ValidationIssue] = field(default_factory=list)
    passed_checks: int = 0
    total_checks: int = 0
    scan_duration: float = 0.0
    details: dict = field(default_factory=dict)

    @property
    def passed(self) -> bool:
        return self.result == ValidationResult.VALID

    @property
    def pass_rate(self) -> float:
        if self.total_checks == 0:
            return 0.0
        return (self.passed_checks / self.total_checks) * 100

    def summary(self) -> str:
        status = "✓ VALID" if self.passed else "✗ ISSUES FOUND"
        return (
            f"{status}\n"
            f"  Checks: {self.passed_checks}/{self.total_checks} passed ({self.pass_rate:.0f}%)\n"
            f"  Issues: {len(self.issues)}\n"
            f"  Duration: {self.scan_duration:.2f}s"
        )


class Recognizer(Program):
    """
    Recognizer - Validation Program that scans for anomalies.

    Recognizers are special Programs that validate work before
    it can proceed. They ensure quality and consistency.
    """

    def __init__(
        self,
        name: str,
        target: str,
        recognizer_type: RecognizerType,
        criteria: list[str] = None,
        parent: Optional[Program] = None,
        energy_budget: int = 50,
    ):
        super().__init__(
            name=name,
            purpose=f"Validate {target}",
            parent=parent,
            energy_budget=energy_budget,
            program_type=ProgramType.RECOGNIZER,
        )

        self.target = target
        self.recognizer_type = recognizer_type
        self.criteria = criteria or []

        # Scan results
        self.scan_result: Optional[ScanResult] = None
        self.issues: list[ValidationIssue] = []

    def add_criterion(self, criterion: str) -> None:
        """Add a validation criterion."""
        if criterion not in self.criteria:
            self.criteria.append(criterion)

    def scan(self, artifacts: list[Any] = None) -> ScanResult:
        """
        Perform validation scan.

        This is a template method - actual validation logic would
        be implemented by specific Recognizer subclasses or external
        validation functions.
        """
        self.start()
        start_time = datetime.now()

        issues = []
        passed = 0
        total = len(self.criteria)

        # Placeholder validation logic
        # In real implementation, this would check actual artifacts
        for criterion in self.criteria:
            # Each criterion is checked
            # For now, all pass (placeholder)
            passed += 1

        duration = (datetime.now() - start_time).total_seconds()

        # Determine result
        if not issues:
            result = ValidationResult.VALID
        elif any(i.severity == "critical" for i in issues):
            result = ValidationResult.DEREZ
        else:
            result = ValidationResult.RECTIFY_NEEDED

        self.scan_result = ScanResult(
            result=result,
            issues=issues,
            passed_checks=passed,
            total_checks=total,
            scan_duration=duration,
        )

        self.issues = issues

        if result == ValidationResult.VALID:
            self.complete(self.scan_result)
        else:
            self.fail(f"Validation failed: {len(issues)} issues found")

        return self.scan_result

    def add_issue(
        self,
        severity: str,
        category: str,
        message: str,
        location: str = None,
        suggestion: str = None,
    ) -> ValidationIssue:
        """Add a validation issue."""
        issue = ValidationIssue(
            severity=severity,
            category=category,
            message=message,
            location=location,
            suggestion=suggestion,
        )
        self.issues.append(issue)
        return issue

    def summary(self) -> str:
        """Get Recognizer summary."""
        lines = [
            f"Recognizer: {self.name} [{self.id}]",
            f"  Type: {self.recognizer_type.value}",
            f"  Target: {self.target}",
            f"  Criteria: {len(self.criteria)}",
            f"  Status: {self.status.value}",
        ]
        if self.scan_result:
            lines.append(f"  Result: {self.scan_result.result.value}")
            lines.append(f"  Issues: {len(self.issues)}")
        return "\n".join(lines)

    def to_dict(self) -> dict:
        """Serialize Recognizer to dictionary."""
        base = super().to_dict()
        base.update({
            "recognizer_type": self.recognizer_type.value,
            "target": self.target,
            "criteria": self.criteria,
            "issues": [i.to_dict() for i in self.issues],
            "scan_result": {
                "result": self.scan_result.result.value,
                "passed_checks": self.scan_result.passed_checks,
                "total_checks": self.scan_result.total_checks,
                "pass_rate": self.scan_result.pass_rate,
            } if self.scan_result else None,
        })
        return base


# Factory functions for common Recognizer types

def create_code_recognizer(
    target: str,
    criteria: list[str] = None,
) -> Recognizer:
    """Create a code quality Recognizer."""
    default_criteria = [
        "No syntax errors",
        "Tests pass",
        "No linting errors",
        "Type checks pass",
    ]
    return Recognizer(
        name=f"code-validator-{target}",
        target=target,
        recognizer_type=RecognizerType.CODE,
        criteria=criteria or default_criteria,
    )


def create_security_recognizer(
    target: str,
    criteria: list[str] = None,
) -> Recognizer:
    """Create a security Recognizer."""
    default_criteria = [
        "No hardcoded secrets",
        "No SQL injection vulnerabilities",
        "No XSS vulnerabilities",
        "Input validation present",
        "Authentication required for protected routes",
    ]
    return Recognizer(
        name=f"security-scanner-{target}",
        target=target,
        recognizer_type=RecognizerType.SECURITY,
        criteria=criteria or default_criteria,
    )


def create_architecture_recognizer(
    target: str,
    criteria: list[str] = None,
) -> Recognizer:
    """Create an architecture Recognizer."""
    default_criteria = [
        "Follows established patterns",
        "Separation of concerns",
        "No circular dependencies",
        "Consistent naming conventions",
    ]
    return Recognizer(
        name=f"architecture-validator-{target}",
        target=target,
        recognizer_type=RecognizerType.ARCHITECTURE,
        criteria=criteria or default_criteria,
    )


def create_consistency_recognizer(
    target: str,
    criteria: list[str] = None,
) -> Recognizer:
    """Create a consistency Recognizer."""
    default_criteria = [
        "All artifacts aligned",
        "Documentation matches implementation",
        "API contracts satisfied",
        "Schema consistency",
    ]
    return Recognizer(
        name=f"consistency-checker-{target}",
        target=target,
        recognizer_type=RecognizerType.CONSISTENCY,
        criteria=criteria or default_criteria,
    )
