"""Pattern validator for Hephaestus."""

from __future__ import annotations

from typing import Any, Dict, List

from ..models.project_context import ProjectContext


class PatternValidator:
    """Validate detected patterns against known patterns and check compatibility."""

    def __init__(self):
        self._pattern_definitions = {
            "material_3": {
                "components": [
                    "NavigationDrawerLayout",
                    "NavigationRailLayout",
                    "TopAppBar",
                    "FloatingActionButton",
                    "Card",
                    "Chip",
                    "DataTable",
                ],
                "roles": [
                    "outlined-button",
                    "filled-button",
                    "tonal-button",
                    "outlined-card",
                    "filled-card",
                    "elevated-card",
                    "outlined-text-field",
                    "filled-text-field",
                ],
                "layouts": ["navigation-drawer", "navigation-rail", "top-app-bar"],
            },
            "reactive": {
                "decorators": ["@reactive_class", "@render_effect"],
                "functions": ["signal", "reactive_instance", "bind"],
                "patterns": ["automatic_updates", "state_management"],
            },
            "routing": {
                "official": ["@anvil.routing.route", "anvil.routing.set_url_hash"],
                "anvil_extras": [
                    "@anvil_extras.routing.route",
                    "anvil_extras.routing.set_url_hash",
                ],
                "custom": ["def route", "url_hash", "navigate_to"],
            },
            "data_layer": {
                "model_classes": ["@anvil.server.model_class", "field(", "Link("],
                "anvil_extras_orm": ["@anvil_extras.orm.model_class", "Model."],
                "raw_tables": ["app_tables.", ".get(", ".add_row("],
            },
        }

    def validate_detected_patterns(
        self, patterns: Dict[str, Any], context: ProjectContext
    ) -> tuple[bool, List[str]]:
        """Validate detected patterns against known patterns."""
        errors = []

        # Validate component patterns
        component_errors = self._validate_component_patterns(
            patterns.get("components", {})
        )
        errors.extend(component_errors)

        # Validate routing patterns
        routing_errors = self._validate_routing_patterns(patterns.get("routing", {}))
        errors.extend(routing_errors)

        # Validate state management patterns
        state_errors = self._validate_state_patterns(
            patterns.get("state_management", {})
        )
        errors.extend(state_errors)

        # Validate data layer patterns
        data_errors = self._validate_data_patterns(patterns.get("data_operations", {}))
        errors.extend(data_errors)

        return len(errors) == 0, errors

    def check_pattern_compatibility(
        self, patterns: Dict[str, Any]
    ) -> Dict[str, List[str]]:
        """Check compatibility between different patterns."""
        compatibility_issues = {"conflicts": [], "warnings": [], "recommendations": []}

        # Check Material 3 vs Classic conflicts
        components = patterns.get("components", {})
        if components.get("material_3_components") and components.get(
            "classic_components"
        ):
            compatibility_issues["warnings"].append(
                "Mixed Material 3 and classic components detected"
            )

        # Check reactive vs traditional state management
        state_mgmt = patterns.get("state_management", {})
        if state_mgmt.get("reactive_patterns") and state_mgmt.get("global_state"):
            compatibility_issues["conflicts"].append(
                "Reactive and global state patterns conflict"
            )

        # Check routing consistency
        routing = patterns.get("routing", {})
        routing_system = routing.get("system")
        if routing_system == "official" and not routing.get("routes"):
            compatibility_issues["warnings"].append(
                "Official routing configured but no routes detected"
            )

        # Check data layer consistency
        data_ops = patterns.get("data_operations", {})
        crud_ops = data_ops.get("crud_operations", [])
        if not crud_ops:
            compatibility_issues["warnings"].append("No CRUD operations detected")

        return compatibility_issues

    def validate_pattern_combinations(self, patterns: Dict[str, Any]) -> List[str]:
        """Validate specific pattern combinations for best practices."""
        recommendations = []

        # Material 3 recommendations
        components = patterns.get("components", {})
        if components.get("material_3_components"):
            if not patterns.get("state_management", {}).get("reactive_patterns"):
                recommendations.append(
                    "Consider using reactive patterns with Material 3 components"
                )

            routing = patterns.get("routing", {})
            if routing.get("system") == "none":
                recommendations.append("Material 3 apps benefit from proper routing")

        # Reactive recommendations
        state_mgmt = patterns.get("state_management", {})
        if state_mgmt.get("reactive_patterns"):
            data_ops = patterns.get("data_operations", {})
            if not data_ops.get("validation_patterns"):
                recommendations.append(
                    "Add validation patterns for reactive data handling"
                )

        # Performance recommendations
        performance = patterns.get("performance_patterns", {})
        opportunities = performance.get("optimization_opportunities", [])
        if "query_optimization" in opportunities:
            recommendations.append("Optimize database queries for better performance")

        return recommendations

    def _validate_component_patterns(
        self, component_patterns: Dict[str, Any]
    ) -> List[str]:
        """Validate component patterns."""
        errors = []

        for pattern_type, components in component_patterns.items():
            if pattern_type == "material_3_components":
                valid_components = self._pattern_definitions["material_3"]["components"]
                for component in components:
                    if component not in valid_components:
                        errors.append(f"Unknown Material 3 component: {component}")

        return errors

    def _validate_routing_patterns(self, routing_patterns: Dict[str, Any]) -> List[str]:
        """Validate routing patterns."""
        errors = []

        system = routing_patterns.get("system")
        if system and system not in ["official", "anvil_extras", "custom", "none"]:
            errors.append(f"Unknown routing system: {system}")

        routes = routing_patterns.get("routes", [])
        for route in routes:
            if not isinstance(route, str) or not route.startswith("/"):
                errors.append(f"Invalid route format: {route}")

        return errors

    def _validate_state_patterns(self, state_patterns: Dict[str, Any]) -> List[str]:
        """Validate state management patterns."""
        errors = []

        reactive_patterns = state_patterns.get("reactive_patterns", [])
        valid_reactive = self._pattern_definitions["reactive"]["functions"]
        for pattern in reactive_patterns:
            if pattern not in valid_reactive:
                errors.append(f"Unknown reactive pattern: {pattern}")

        return errors

    def _validate_data_patterns(self, data_patterns: Dict[str, Any]) -> List[str]:
        """Validate data operation patterns."""
        errors = []

        crud_ops = data_patterns.get("crud_operations", [])
        valid_crud = ["create", "read", "update", "delete"]
        for op in crud_ops:
            if op not in valid_crud:
                errors.append(f"Unknown CRUD operation: {op}")

        return errors
