"""Project analyzer for Hephaestus."""

from __future__ import annotations

import re
from pathlib import Path
from typing import Any, Dict, List, Optional

from ..dependencies.container import FileSystem, ProjectManager
from ..models.project_context import (
    ProjectContext,
)


class ProjectAnalyzer:
    """Analyze Anvil projects to determine patterns and context."""

    def __init__(self, file_system: FileSystem, project_manager: ProjectManager):
        self.file_system = file_system
        self.project_manager = project_manager

        # Pattern detection patterns
        self._component_patterns = {
            "material_3": [
                r"material-?3",
                r"NavigationDrawerLayout",
                r"NavigationRailLayout",
                r"role:\s*['\"](?:outlined|elevated|filled)-['\"]",
                r"@theme\.m3_",
            ],
            "material_design": [r"material[-\s]design", r"mdc-", r"MaterialComponents"],
            "shoelace": [r"shoelace", r"@sl/", r"sl-"],
            "classic": [r"anvil\.", r"ColumnPanel", r"FlowPanel", r"GridPanel"],
        }

        self._routing_patterns = {
            "official": [
                r"from anvil\.routing",
                r"@anvil\.routing\.route",
                r"anvil\.routing\.set_url_hash",
                r"anvil\.routing\.get_url_hash",
            ],
            "anvil_extras": [
                r"from anvil_extras\.routing",
                r"@anvil_extras\.routing\.route",
                r"anvil_extras\.routing\.set_url_hash",
            ],
            "custom": [r"def.*route", r"url_hash", r"navigate_to", r"router"],
        }

        self._reactive_patterns = [
            r"from anvil_extras\.reactive",
            r"@reactive_class",
            r"signal\(",
            r"reactive_instance\(",
            r"bind\(",
            r"@render_effect",
        ]

        self._data_layer_patterns = {
            "model_classes": [
                r"@anvil\.server\.model_class",
                r"field\(",
                r"Link\(",
                r"Query\(",
            ],
            "anvil_extras_orm": [
                r"from anvil_extras\.orm",
                r"@anvil_extras\.orm\.model_class",
                r"Model\.",
            ],
            "raw_tables": [r"app_tables\.", r"\.get\(", r"\.search\(", r"\.add_row\("],
        }

    def analyze_project(self, project_path: Path) -> ProjectContext:
        """Analyze project and return comprehensive context."""
        if not self.project_manager.is_anvil_project(project_path):
            raise ValueError(f"Not an Anvil project: {project_path}")

        # Basic project info
        project_name = project_path.name
        capability_level = self._detect_capability_level(project_path)

        # Architecture patterns
        theme_type = self._detect_theme_type(project_path)
        routing_system = self._detect_routing_system(project_path)
        has_reactive = self._detect_reactive_usage(project_path)
        data_layer = self._detect_data_layer(project_path)
        layout_system = self._detect_layout_system(project_path)

        # Analysis metrics
        modernisation_score = self._calculate_modernisation_score(
            theme_type, routing_system, has_reactive, data_layer, layout_system
        )
        generation_mode = self._determine_generation_mode(modernisation_score)
        complexity_score = self._calculate_complexity_score(project_path)
        maintainability_index = self._calculate_maintainability_index(project_path)

        # Component analysis
        component_count = self._count_components(project_path)
        form_count = self._count_forms(project_path)
        server_function_count = self._count_server_functions(project_path)
        custom_component_count = self._count_custom_components(project_path)

        # Pattern analysis
        detected_patterns = self.detect_comprehensive_patterns(project_path)
        architecture_patterns = self._identify_architecture_patterns(detected_patterns)
        anti_patterns = self._identify_anti_patterns(detected_patterns)

        # Recommendations
        performance_opportunities = self._identify_performance_opportunities(
            theme_type, routing_system, has_reactive, data_layer, layout_system
        )
        breaking_change_risks = self._identify_breaking_change_risks(
            theme_type, routing_system, has_reactive, data_layer, layout_system
        )
        modernisation_suggestions = self._generate_modernisation_suggestions(
            modernisation_score, detected_patterns
        )
        security_recommendations = self._generate_security_recommendations(
            detected_patterns
        )

        # Metadata
        from datetime import datetime

        analysis_timestamp = datetime.now().isoformat()

        return ProjectContext(
            project_path=project_path,
            project_name=project_name,
            capability_level=capability_level,
            theme_type=theme_type,
            routing_system=routing_system,
            has_reactive=has_reactive,
            data_layer=data_layer,
            layout_system=layout_system,
            modernisation_score=modernisation_score,
            generation_mode=generation_mode,
            complexity_score=complexity_score,
            maintainability_index=maintainability_index,
            component_count=component_count,
            form_count=form_count,
            server_function_count=server_function_count,
            custom_component_count=custom_component_count,
            detected_patterns=detected_patterns,
            architecture_patterns=architecture_patterns,
            anti_patterns=anti_patterns,
            performance_opportunities=performance_opportunities,
            breaking_change_risks=breaking_change_risks,
            modernisation_suggestions=modernisation_suggestions,
            security_recommendations=security_recommendations,
            analysis_timestamp=analysis_timestamp,
        )

    def _detect_theme_type(self, project_path: Path) -> str:
        """Detect the theme type used in the project."""
        theme_files = self.project_manager.get_project_files(project_path, "theme/**/*")

        for theme_file in theme_files:
            content = self.file_system.read_text(theme_file)
            if "material-3" in content.lower() or "m3" in content.lower():
                return "material-3"
            elif "material" in content.lower():
                return "material"
            elif "shoelace" in content.lower():
                return "shoelace"

        return "classic"

    def _detect_routing_system(self, project_path: Path) -> str:
        """Detect the routing system used."""
        server_files = self.project_manager.get_project_files(
            project_path, "server_code/**/*.py"
        )

        for server_file in server_files:
            content = self.file_system.read_text(server_file)
            if "from anvil_extras.routing" in content:
                return "anvil-extras"
            elif "from anvil.routing" in content or "@anvil.routing.route" in content:
                return "official"

        return "none"

    def _detect_reactive_usage(self, project_path: Path) -> bool:
        """Detect if reactive library is used."""
        client_files = self.project_manager.get_project_files(
            project_path, "client_code/**/*.py"
        )

        for client_file in client_files:
            content = self.file_system.read_text(client_file)
            if "from anvil_extras.reactive" in content or "@reactive_class" in content:
                return True

        return False

    def _detect_data_layer(self, project_path: Path) -> str:
        """Detect the data layer approach."""
        server_files = self.project_manager.get_project_files(
            project_path, "server_code/**/*.py"
        )

        for server_file in server_files:
            content = self.file_system.read_text(server_file)
            if "@anvil.server.model_class" in content:
                return "model-classes"
            elif "from anvil_extras.orm" in content:
                return "anvil-extras-orm"
            elif "app_tables." in content:
                return "raw-tables"

        return "unknown"

    def _detect_capability_level(self, project_path: Path) -> str:
        """Detect capability level based on available features."""
        # Check for capability indicators in various files
        capability_files = [
            "anvil.yaml",
            "anvil.json",
            "requirements.txt",
            "pyproject.toml",
        ]

        for filename in capability_files:
            file_path = project_path / filename
            if file_path.exists():
                capability = self._extract_capability_from_file(file_path)
                if capability:
                    return capability

        # Analyze code patterns for capability detection
        theme_type = self._detect_theme_type(project_path)
        routing_system = self._detect_routing_system(project_path)
        has_reactive = self._detect_reactive_usage(project_path)
        data_layer = self._detect_data_layer(project_path)
        layout_system = self._detect_layout_system(project_path)

        # Determine capability level based on feature combination
        if (
            theme_type == "material-3"
            and routing_system == "official"
            and has_reactive
            and data_layer == "model-classes"
        ):
            return "cutting-edge"
        elif (
            theme_type == "material-3"
            and has_reactive
            and data_layer == "model-classes"
        ):
            return "modern"
        elif (
            routing_system == "official"
            and has_reactive
            and data_layer == "model-classes"
        ):
            return "advanced"
        elif has_reactive and data_layer == "model-classes":
            return "intermediate"
        elif has_reactive or data_layer == "model-classes":
            return "enhanced"
        elif theme_type != "classic":
            return "basic"
        else:
            return "basic"

    def _extract_capability_from_file(self, file_path: Path) -> Optional[str]:
        """Extract capability level information from a file."""
        try:
            content = self.file_system.read_text(file_path)

            # Look for capability indicators
            if "material-3" in content.lower() or "@anvil/material-3" in content:
                return "advanced" if "layout" in content.lower() else "modern"
            elif "official-routing" in content.lower() or "anvil.routing" in content:
                return "intermediate"
            elif "reactive" in content.lower() or "anvil.reactive" in content:
                return "intermediate"
            elif "model_class" in content.lower() or "model_classes" in content:
                return "intermediate"
            elif "tabulator" in content.lower():
                return "intermediate"
            elif "validation" in content.lower():
                return "enhanced"
            elif "theme" in content.lower():
                return "basic"

            return None
        except Exception:
            return None

    def _detect_layout_system(self, project_path: Path) -> str:
        """Detect the layout system used."""
        client_files = self.project_manager.get_project_files(
            project_path, "client_code/**/*.py"
        )

        for client_file in client_files:
            content = self.file_system.read_text(client_file)
            if "NavigationDrawerLayout" in content or "NavigationRailLayout" in content:
                return "layouts"
            elif "ColumnPanel" in content or "FlowPanel" in content:
                return "traditional"

        return "mixed"

    def _calculate_modernisation_score(
        self,
        theme_type: str,
        routing_system: str,
        has_reactive: bool,
        data_layer: str,
        layout_system: str,
    ) -> float:
        """Calculate modernisation score based on detected patterns."""
        score = 0.0

        # Theme scoring
        if theme_type == "material-3":
            score += 0.25
        elif theme_type == "material":
            score += 0.15
        elif theme_type == "shoelace":
            score += 0.1

        # Routing scoring
        if routing_system == "official":
            score += 0.25
        elif routing_system == "anvil-extras":
            score += 0.15

        # Reactive scoring
        if has_reactive:
            score += 0.2

        # Data layer scoring
        if data_layer == "model-classes":
            score += 0.2
        elif data_layer == "anvil-extras-orm":
            score += 0.1

        # Layout scoring
        if layout_system == "layouts":
            score += 0.1
        elif layout_system == "mixed":
            score += 0.05

        return min(score, 1.0)

    def _determine_generation_mode(self, modernisation_score: float) -> str:
        """Determine generation mode based on modernisation score."""
        if modernisation_score >= 0.8:
            return "modern"
        elif modernisation_score >= 0.4:
            return "hybrid"
        else:
            return "legacy-compatible"

    def _identify_performance_opportunities(
        self,
        theme_type: str,
        routing_system: str,
        has_reactive: bool,
        data_layer: str,
        layout_system: str,
    ) -> list[str]:
        """Identify performance optimization opportunities."""
        opportunities = []

        if not has_reactive:
            opportunities.append("reactive-optimisation")

        if layout_system == "traditional":
            opportunities.append("layout-improvements")

        if data_layer == "raw-tables":
            opportunities.append("data-layer-modernisation")

        if routing_system == "none":
            opportunities.append("routing-implementation")

        if theme_type == "classic":
            opportunities.append("theme-upgrade")

        return opportunities

    def _identify_breaking_change_risks(
        self,
        theme_type: str,
        routing_system: str,
        has_reactive: bool,
        data_layer: str,
        layout_system: str,
    ) -> list[str]:
        """Identify potential breaking change risks."""
        risks = []

        if data_layer == "raw-tables":
            risks.append("data-layer-migration")

        if routing_system == "anvil-extras":
            risks.append("routing-migration")

        if layout_system == "traditional":
            risks.append("layout-refactoring")

        return risks

    def detect_comprehensive_patterns(self, project_path: Path) -> Dict[str, Any]:
        """Detect comprehensive patterns across the entire project."""
        patterns = {
            "components": self._detect_component_patterns(project_path),
            "routing": self._detect_routing_patterns_detailed(project_path),
            "state_management": self._detect_state_management_patterns(project_path),
            "data_operations": self._detect_data_operation_patterns(project_path),
            "ui_patterns": self._detect_ui_patterns(project_path),
            "security_patterns": self._detect_security_patterns(project_path),
            "performance_patterns": self._detect_performance_patterns(project_path),
            "testing_patterns": self._detect_testing_patterns(project_path),
        }
        return patterns

    def _detect_component_patterns(self, project_path: Path) -> Dict[str, List[str]]:
        """Detect detailed component usage patterns."""
        client_files = self.project_manager.get_project_files(
            project_path, "client_code/**/*.py"
        )

        patterns = {
            "material_3_components": [],
            "classic_components": [],
            "custom_components": [],
            "layout_patterns": [],
            "form_patterns": [],
        }

        m3_components = {
            "NavigationDrawerLayout",
            "NavigationRailLayout",
            "TopAppBar",
            "FloatingActionButton",
            "Card",
            "Chip",
            "DataTable",
        }

        classic_components = {
            "ColumnPanel",
            "FlowPanel",
            "GridPanel",
            "XYPanel",
            "LinearPanel",
            "RepeatingPanel",
            "DataGrid",
            "Button",
            "TextBox",
            "Label",
        }

        for file_path in client_files:
            content = self.file_system.read_text(file_path)

            # Detect Material 3 components
            for component in m3_components:
                if re.search(rf"\b{component}\b", content):
                    patterns["material_3_components"].append(component)

            # Detect classic components
            for component in classic_components:
                if re.search(rf"\b{component}\b", content):
                    patterns["classic_components"].append(component)

            # Detect custom components
            custom_matches = re.findall(r"form:\w+:\w+\.\w+", content)
            patterns["custom_components"].extend(custom_matches)

            # Detect layout patterns
            if re.search(r"\.add_component\(", content):
                patterns["layout_patterns"].append("dynamic_add")
            if re.search(r"self\.init_components", content):
                patterns["layout_patterns"].append("declarative")

        return patterns

    def _detect_routing_patterns_detailed(self, project_path: Path) -> Dict[str, Any]:
        """Detect detailed routing patterns."""
        server_files = self.project_manager.get_project_files(
            project_path, "server_code/**/*.py"
        )
        client_files = self.project_manager.get_project_files(
            project_path, "client_code/**/*.py"
        )

        routes_list = []
        navigation_patterns_list = []
        data_loading_list = []

        all_files = server_files + client_files

        for file_path in all_files:
            content = self.file_system.read_text(file_path)

            # Detect route definitions
            route_matches = re.findall(r'@.*route\([\'"]([^\'"]+)[\'"]', content)
            routes_list.extend(route_matches)

            # Detect navigation patterns
            if re.search(r"anvil\.open_form", content):
                navigation_patterns_list.append("open_form")
            if re.search(r"set_url_hash", content):
                navigation_patterns_list.append("hash_routing")
            if re.search(r"get_url_hash", content):
                navigation_patterns_list.append("hash_reading")

            # Detect data loading patterns
            if re.search(r"load_data\(", content):
                data_loading_list.append("explicit_load")
            if re.search(r"routing_context", content):
                data_loading_list.append("context_data")

        routing_info = {
            "system": self._detect_routing_system(project_path),
            "routes": routes_list,
            "navigation_patterns": navigation_patterns_list,
            "data_loading": data_loading_list,
        }

        return routing_info

    def _detect_state_management_patterns(
        self, project_path: Path
    ) -> Dict[str, List[str]]:
        """Detect state management patterns."""
        client_files = self.project_manager.get_project_files(
            project_path, "client_code/**/*.py"
        )

        patterns = {
            "reactive_patterns": [],
            "global_state": [],
            "form_state": [],
            "server_state": [],
        }

        for file_path in client_files:
            content = self.file_system.read_text(file_path)

            # Reactive patterns
            if re.search(r"signal\(", content):
                patterns["reactive_patterns"].append("signals")
            if re.search(r"reactive_instance\(", content):
                patterns["reactive_patterns"].append("reactive_instances")
            if re.search(r"@render_effect", content):
                patterns["reactive_patterns"].append("render_effects")
            if re.search(r"bind\(", content):
                patterns["reactive_patterns"].append("bindings")

            # Global state patterns
            if re.search(r"global\s+\w+", content):
                patterns["global_state"].append("global_variables")
            if re.search(r"__init__\s*=\s*{", content):
                patterns["global_state"].append("module_dicts")

            # Form state patterns
            if re.search(r"self\.\w+\s*=", content):
                patterns["form_state"].append("form_properties")

            # Server state patterns
            if re.search(r"anvil\.server\.call", content):
                patterns["server_state"].append("server_calls")

        return patterns

    def _detect_data_operation_patterns(
        self, project_path: Path
    ) -> Dict[str, List[str]]:
        """Detect data operation patterns."""
        server_files = self.project_manager.get_project_files(
            project_path, "server_code/**/*.py"
        )

        patterns = {
            "crud_operations": [],
            "query_patterns": [],
            "validation_patterns": [],
            "transaction_patterns": [],
        }

        for file_path in server_files:
            content = self.file_system.read_text(file_path)

            # CRUD operations
            if re.search(r"\.add_row\(", content):
                patterns["crud_operations"].append("create")
            if re.search(r"\.get\(", content):
                patterns["crud_operations"].append("read")
            if re.search(r"\.update\(\)", content):
                patterns["crud_operations"].append("update")
            if re.search(r"\.delete\(\)", content):
                patterns["crud_operations"].append("delete")

            # Query patterns
            if re.search(r"\.search\(", content):
                patterns["query_patterns"].append("search")
            if re.search(r"\.order_by\(", content):
                patterns["query_patterns"].append("ordering")
            if re.search(r"\.limit\(", content):
                patterns["query_patterns"].append("limiting")

            # Validation patterns
            if re.search(r"raise\s+ValueError", content):
                patterns["validation_patterns"].append("value_validation")
            if re.search(r"assert\s+", content):
                patterns["validation_patterns"].append("assertions")

            # Transaction patterns
            if re.search(r"@anvil\.server\.callable", content):
                patterns["transaction_patterns"].append("server_functions")

        return patterns

    def _detect_ui_patterns(self, project_path: Path) -> Dict[str, List[str]]:
        """Detect UI interaction patterns."""
        client_files = self.project_manager.get_project_files(
            project_path, "client_code/**/*.py"
        )

        patterns = {
            "event_handling": [],
            "form_interactions": [],
            "data_display": [],
            "user_input": [],
        }

        for file_path in client_files:
            content = self.file_system.read_text(file_path)

            # Event handling patterns
            event_matches = re.findall(
                r"def\s+(\w+)_(click|change|submit|focus|blur)", content
            )
            patterns["event_handling"].extend(
                [f"{event}_{type_}" for event, type_ in event_matches]
            )

            # Form interactions
            if re.search(r"self\.refresh_data_bindings\(\)", content):
                patterns["form_interactions"].append("data_binding_refresh")
            if re.search(r"self\.clear\(\)", content):
                patterns["form_interactions"].append("form_clear")

            # Data display patterns
            if re.search(r"DataGrid", content):
                patterns["data_display"].append("data_grid")
            if re.search(r"RepeatingPanel", content):
                patterns["data_display"].append("repeating_panel")

            # User input patterns
            if re.search(r"TextBox", content):
                patterns["user_input"].append("text_input")
            if re.search(r"DropDown", content):
                patterns["user_input"].append("selection_input")
            if re.search(r"CheckBox", content):
                patterns["user_input"].append("boolean_input")

        return patterns

    def _detect_security_patterns(self, project_path: Path) -> Dict[str, List[str]]:
        """Detect security patterns."""
        server_files = self.project_manager.get_project_files(
            project_path, "server_code/**/*.py"
        )

        patterns = {
            "authentication": [],
            "authorization": [],
            "input_validation": [],
            "data_protection": [],
        }

        for file_path in server_files:
            content = self.file_system.read_text(file_path)

            # Authentication patterns
            if re.search(r"anvil\.users\.get_user\(\)", content):
                patterns["authentication"].append("user_lookup")
            if re.search(r"anvil\.users\.force_login", content):
                patterns["authentication"].append("login_enforcement")

            # Authorization patterns
            if re.search(r"@anvil\.server\.callable", content):
                patterns["authorization"].append("server_callable")
            if re.search(r"if\s+anvil\.users\.get_user\(\)", content):
                patterns["authorization"].append("user_check")

            # Input validation
            if re.search(r"isinstance\(", content):
                patterns["input_validation"].append("type_checking")
            if re.search(r"len\(", content):
                patterns["input_validation"].append("length_validation")

            # Data protection
            if re.search(r"anvil\.server\.no_ui_call", content):
                patterns["data_protection"].append("ui_restriction")

        return patterns

    def _detect_performance_patterns(self, project_path: Path) -> Dict[str, List[str]]:
        """Detect performance-related patterns."""
        all_files = self.project_manager.get_project_files(project_path, "**/*.py")

        patterns = {
            "optimization_opportunities": [],
            "anti_patterns": [],
            "good_practices": [],
        }

        for file_path in all_files:
            content = self.file_system.read_text(file_path)

            # Optimization opportunities
            if re.search(r"app_tables\.\w+\.search\(\)", content):
                patterns["optimization_opportunities"].append("query_optimization")
            if re.search(r"for.*in.*range\(.*len\(", content):
                patterns["optimization_opportunities"].append("loop_optimization")

            # Anti-patterns
            if re.search(r"global\s+\w+", content):
                patterns["anti_patterns"].append("global_state")
            if re.search(r"eval\(", content):
                patterns["anti_patterns"].append("dynamic_code")

            # Good practices
            if re.search(r"try:", content):
                patterns["good_practices"].append("error_handling")
            if re.search(r"with\s+open", content):
                patterns["good_practices"].append("resource_management")

        return patterns

    def _detect_testing_patterns(self, project_path: Path) -> Dict[str, List[str]]:
        """Detect testing patterns."""
        test_files = self.project_manager.get_project_files(
            project_path, "**/*test*.py"
        )

        patterns = {"test_frameworks": [], "test_types": [], "coverage_areas": []}

        for file_path in test_files:
            content = self.file_system.read_text(file_path)

            # Test frameworks
            if re.search(r"import\s+pytest", content):
                patterns["test_frameworks"].append("pytest")
            if re.search(r"import\s+unittest", content):
                patterns["test_frameworks"].append("unittest")

            # Test types
            if re.search(r"def test_.*unit", content):
                patterns["test_types"].append("unit_tests")
            if re.search(r"def test_.*integration", content):
                patterns["test_types"].append("integration_tests")

            # Coverage areas
            if re.search(r"test_.*form", content):
                patterns["coverage_areas"].append("form_testing")
            if re.search(r"test_.*server", content):
                patterns["coverage_areas"].append("server_testing")

        return patterns

    def _count_components(self, project_path: Path) -> int:
        """Count total components in project."""
        client_files = self.project_manager.get_project_files(
            project_path, "client_code/**/*.py"
        )
        return len(client_files)

    def _count_forms(self, project_path: Path) -> int:
        """Count forms in project."""
        client_files = self.project_manager.get_project_files(
            project_path, "client_code/**/*.py"
        )
        form_count = 0
        for file_path in client_files:
            content = self.file_system.read_text(file_path)
            if "anvil.Form" in content or "anvil.open_form" in content:
                form_count += 1
        return form_count

    def _count_server_functions(self, project_path: Path) -> int:
        """Count server functions in project."""
        server_files = self.project_manager.get_project_files(
            project_path, "server_code/**/*.py"
        )
        function_count = 0
        for file_path in server_files:
            content = self.file_system.read_text(file_path)
            function_count += len(re.findall(r"@anvil\.server\.callable", content))
        return function_count

    def _count_custom_components(self, project_path: Path) -> int:
        """Count custom components in project."""
        client_files = self.project_manager.get_project_files(
            project_path, "client_code/**/*.py"
        )
        custom_count = 0
        for file_path in client_files:
            content = self.file_system.read_text(file_path)
            if "anvil.CustomComponent" in content:
                custom_count += 1
        return custom_count

    def _identify_architecture_patterns(
        self, detected_patterns: Dict[str, Any]
    ) -> List[str]:
        """Identify architecture patterns from detected patterns."""
        patterns = []

        if detected_patterns.get("component_patterns"):
            patterns.extend(detected_patterns["component_patterns"])

        if detected_patterns.get("routing_patterns"):
            patterns.extend(detected_patterns["routing_patterns"])

        return patterns

    def _identify_anti_patterns(self, detected_patterns: Dict[str, Any]) -> List[str]:
        """Identify anti-patterns from detected patterns."""
        return detected_patterns.get("anti_patterns", [])

    def _identify_performance_opportunities(
        self,
        theme_type: str,
        routing_system: str,
        has_reactive: bool,
        data_layer: str,
        layout_system: str,
    ) -> List[str]:
        """Identify performance optimization opportunities."""
        opportunities = []

        if not has_reactive:
            opportunities.append("reactive-optimisation")

        if layout_system == "traditional":
            opportunities.append("layout-improvements")

        if data_layer == "raw-tables":
            opportunities.append("database-optimization")

        return opportunities

    def _identify_breaking_change_risks(
        self,
        theme_type: str,
        routing_system: str,
        has_reactive: bool,
        data_layer: str,
        layout_system: str,
    ) -> List[str]:
        """Identify potential breaking change risks."""
        risks = []

        if theme_type == "classic" and layout_system == "traditional":
            risks.append("theme-upgrade-required")

        if routing_system == "anvil-extras":
            risks.append("routing-migration-required")

        return risks

    def _generate_modernisation_suggestions(
        self, modernisation_score: float, detected_patterns: Dict[str, Any]
    ) -> List[str]:
        """Generate modernisation suggestions."""
        suggestions = []

        if modernisation_score < 0.4:
            suggestions.append("upgrade-to-modern-stack")

        if modernisation_score < 0.8:
            suggestions.append("implement-reactive-patterns")

        return suggestions

    def _generate_security_recommendations(
        self, detected_patterns: Dict[str, Any]
    ) -> List[str]:
        """Generate security recommendations."""
        recommendations = []

        anti_patterns = detected_patterns.get("anti_patterns", [])
        if "global_state" in anti_patterns:
            recommendations.append("avoid-global-state")

        if "dynamic_code" in anti_patterns:
            recommendations.append("avoid-dynamic-code-execution")

        return recommendations

    def _calculate_complexity_score(self, project_path: Path) -> float:
        """Calculate project complexity score."""
        try:
            client_files = self.project_manager.get_project_files(
                project_path, "client_code/**/*.py"
            )
            server_files = self.project_manager.get_project_files(
                project_path, "server_code/**/*.py"
            )

            total_files = len(client_files) + len(server_files)

            # Base complexity on file count and estimated size
            if total_files < 10:
                return 0.2
            elif total_files < 25:
                return 0.5
            elif total_files < 50:
                return 0.7
            else:
                return 0.9
        except Exception:
            return 0.5

    def _calculate_maintainability_index(self, project_path: Path) -> float:
        """Calculate maintainability index."""
        # Simple heuristic based on patterns detected
        try:
            patterns = self.detect_comprehensive_patterns(project_path)

            # Start with base score
            score = 0.5

            # Penalize anti-patterns
            anti_patterns = patterns.get("anti_patterns", [])
            score -= len(anti_patterns) * 0.1

            # Reward good practices
            good_practices = patterns.get("good_practices", [])
            score += len(good_practices) * 0.05

            return max(0.0, min(1.0, score))
        except Exception:
            return 0.5
