# app/services/scoring_engine.py
from typing import Any, Dict, List, Optional, Tuple
import math
from geopy.distance import geodesic

from app.models.green_space import (
    GreenSpace, PersonalityScore, LocationScore, 
    Coordinates, Amenity, AmenityType
)
from app.services.berlin_data_service import BerlinDataService
from app.services.street_tree_service import StreetTreeService

class ScoringEngine:
    """Dynamic scoring engine for green spaces based on personality preferences."""
    
    def __init__(self):
        self.berlin_data = BerlinDataService()
        self.street_tree_service = StreetTreeService()
        self.personality_weights = self._initialize_personality_weights()
    
    def _initialize_personality_weights(self) -> Dict[str, Dict[str, float]]:
        """Define scoring weights for each personality type."""
        return {
            "little_adventurers": {
                "playground_quality": 25,
                "safety_score": 20,
                "toilet_proximity": 15,
                "shade_quality": 10,
                "noise_level": 10,  # Lower noise = higher score
                "family_amenities": 15,
                "accessibility": 5
            },
            "date_night": {
                "romantic_atmosphere": 25,
                "noise_level": 20,  # Quiet = romantic
                "scenic_beauty": 20,
                "restaurant_proximity": 15,
                "privacy_score": 10,
                "lighting_quality": 10
            },
            "squad_goals": {
                "space_size": 25,
                "group_amenities": 20,
                "accessibility": 15,
                "food_options": 15,
                "parking_availability": 10,
                "activity_options": 15
            },
            "zen_masters": {
                "quietness": 30,
                "nature_immersion": 25,
                "crowd_density": 15,  # Lower crowds = higher score
                "water_features": 10,
                "meditation_spots": 10,
                "air_quality": 10
            },
            "active_lifestyle": {
                "fitness_facilities": 25,
                "running_cycling_paths": 25,
                "sports_areas": 20,
                "accessibility": 15,
                "terrain_variety": 10,
                "safety_score": 5
            },
            "wildlife_lover": {
                "wildlife_diversity": 30,
                "natural_habitat": 25,
                "water_features": 15,
                "tree_coverage": 15,
                "noise_level": 10,  # Quiet for animals
                "observation_spots": 5
            },
            "art_nerd": {
                "cultural_proximity": 30,
                "artistic_features": 20,
                "museum_accessibility": 20,
                "creative_atmosphere": 15,
                "cafe_culture": 10,
                "inspiring_views": 5
            },
            "history_geek": {
                "historical_significance": 35,
                "monument_proximity": 25,
                "educational_value": 20,
                "architectural_features": 10,
                "cultural_context": 10
            }
        }
    
    async def score_green_space(
        self, 
        green_space: GreenSpace, 
        personality: str,
        user_location: Optional[Tuple[float, float]] = None
    ) -> PersonalityScore:
        """Score a green space for a specific personality type."""
        
        weights = self.personality_weights.get(personality, {})
        if not weights:
            raise ValueError(f"Unknown personality type: {personality}")
        
        # Pre-fetch tree data once for all calculations
        tree_data = await self._fetch_tree_data_once(green_space)
        
        # Calculate component scores with cached tree data
        component_scores = await self._calculate_component_scores(
            green_space, personality, user_location, tree_data
        )
        
        # Calculate weighted final score
        final_score = 0
        explanation_parts = []
        key_factors = []
        
        for component, weight in weights.items():
            if component in component_scores:
                component_score = component_scores[component]
                weighted_score = (component_score * weight) / 100
                final_score += weighted_score
                
                if component_score > 70:  # Highlight strong factors
                    key_factors.append(component)
                    explanation_parts.append(
                        f"{component.replace('_', ' ')}: {component_score}/100"
                    )
        
        # Generate recommendations
        recommendations = self._generate_recommendations(
            green_space, personality, component_scores
        )
        
        return PersonalityScore(
            personality=personality,
            score=min(100, max(0, int(final_score))),
            explanation=self._create_explanation(personality, explanation_parts),
            key_factors=key_factors,
            recommendations=recommendations
        )
    
    async def _fetch_tree_data_once(self, green_space: GreenSpace) -> Optional[Any]:
        """Fetch tree data once and reuse for all calculations."""
        try:
            # Use the largest radius needed across all methods (400m)
            tree_response = await self.street_tree_service.get_trees_near_location(
                green_space.coordinates.lat, 
                green_space.coordinates.lng, 
                radius_m=400
            )
            return tree_response
        except Exception as e:
            print(f"Error fetching tree data: {e}")
            return None
    
    async def _calculate_component_scores(
        self, 
        green_space: GreenSpace, 
        personality: str,
        user_location: Optional[Tuple[float, float]] = None,
        tree_data: Optional[Any] = None
    ) -> Dict[str, int]:
        """Calculate individual component scores."""
        scores = {}
        
        # Universal components
        scores["accessibility"] = self._score_accessibility(green_space, user_location)
        scores["safety_score"] = self._score_safety(green_space)
        scores["noise_level"] = self._score_noise_level(green_space)
        
        # Personality-specific components
        if personality == "little_adventurers":
            scores["playground_quality"] = green_space.recreation.playground_quality
            scores["shade_quality"] = self._score_shade_quality_with_trees(green_space, tree_data)
            scores["toilet_proximity"] = await self._score_toilet_proximity(green_space)
            scores["family_amenities"] = await self._score_family_amenities(green_space)
        
        elif personality == "date_night":
            scores["romantic_atmosphere"] = await self._score_romantic_atmosphere(green_space)
            scores["scenic_beauty"] = self._score_scenic_beauty(green_space)
            scores["restaurant_proximity"] = await self._score_restaurant_proximity(green_space)
            scores["privacy_score"] = self._score_privacy(green_space)
            scores["lighting_quality"] = green_space.accessibility.lighting_quality * 20
        
        elif personality == "squad_goals":
            scores["space_size"] = self._score_space_size(green_space)
            scores["group_amenities"] = await self._score_group_amenities(green_space)
            scores["food_options"] = await self._score_food_options(green_space)
            scores["parking_availability"] = green_space.accessibility.parking_availability * 20
            scores["activity_options"] = self._score_activity_options(green_space)
        
        elif personality == "zen_masters":
            scores["quietness"] = self._score_quietness(green_space)
            scores["nature_immersion"] = self._score_nature_immersion_with_trees(green_space, tree_data)
            scores["crowd_density"] = await self._score_crowd_density(green_space)
            scores["water_features"] = 100 if green_space.environmental.water_features else 0
            scores["meditation_spots"] = self._score_meditation_spots_with_trees(green_space, tree_data)
            scores["air_quality"] = self._score_air_quality_with_trees(green_space, tree_data)
        
        elif personality == "active_lifestyle":
            scores["fitness_facilities"] = 100 if green_space.recreation.sports_facilities else 0
            scores["running_cycling_paths"] = self._score_running_cycling_paths(green_space)
            scores["sports_areas"] = self._score_sports_areas(green_space)
            scores["terrain_variety"] = self._score_terrain_variety(green_space)
        
        elif personality == "wildlife_lover":
            scores["wildlife_diversity"] = self._score_wildlife_diversity_with_trees(green_space, tree_data)
            scores["natural_habitat"] = self._score_natural_habitat_with_trees(green_space, tree_data)
            scores["water_features"] = 100 if green_space.environmental.water_features else 0
            scores["tree_coverage"] = self._score_tree_coverage_with_real_data(green_space, tree_data)
            scores["observation_spots"] = self._score_observation_spots_with_trees(green_space, tree_data)
        
        elif personality == "art_nerd":
            scores["cultural_proximity"] = await self._score_cultural_proximity(green_space)
            scores["artistic_features"] = await self._score_artistic_features(green_space)
            scores["museum_accessibility"] = await self._score_museum_accessibility(green_space)
            scores["creative_atmosphere"] = self._score_creative_atmosphere(green_space)
            scores["cafe_culture"] = await self._score_cafe_culture(green_space)
            scores["inspiring_views"] = self._score_inspiring_views(green_space)
        
        elif personality == "history_geek":
            scores["historical_significance"] = await self._score_historical_significance(green_space)
            scores["monument_proximity"] = await self._score_monument_proximity(green_space)
            scores["educational_value"] = self._score_educational_value(green_space)
            scores["architectural_features"] = self._score_architectural_features(green_space)
            scores["cultural_context"] = await self._score_cultural_context(green_space)
        
        return scores
    
    # === COMPONENT SCORING METHODS ===
    
    def _score_accessibility(self, green_space: GreenSpace, user_location: Optional[Tuple[float, float]]) -> int:
        """Score overall accessibility."""
        score = green_space.accessibility.public_transport_score * 20
        
        if green_space.accessibility.wheelchair_accessible:
            score += 20
        
        if user_location:
            distance = geodesic(
                user_location,
                (green_space.coordinates.lat, green_space.coordinates.lng)
            ).meters
            # Score based on distance (closer = better)
            if distance <= 500:
                score += 20
            elif distance <= 1000:
                score += 15
            elif distance <= 2000:
                score += 10
            else:
                score += 5
        
        return min(100, score)
    
    def _score_safety(self, green_space: GreenSpace) -> int:
        """Score safety based on lighting and accessibility."""
        score = green_space.accessibility.lighting_quality * 15
        if green_space.accessibility.wheelchair_accessible:
            score += 20
        score += green_space.accessibility.public_transport_score * 10
        return min(100, score)
    
    def _score_noise_level(self, green_space: GreenSpace) -> int:
        """Score based on noise level (lower noise = higher score)."""
        return (6 - green_space.environmental.noise_level.value) * 20
    
    async def _score_toilet_proximity(self, green_space: GreenSpace) -> int:
        """Score based on toilet proximity."""
        toilets = [a for a in green_space.nearby_amenities if a.type == AmenityType.TOILET]
        if not toilets:
            return 20  # Assume some basic facilities
        closest_distance = min(toilet.distance_meters for toilet in toilets)
        if closest_distance <= 100:
            return 100
        elif closest_distance <= 300:
            return 80
        elif closest_distance <= 500:
            return 60
        else:
            return 40
    
    async def _score_family_amenities(self, green_space: GreenSpace) -> int:
        """Score family-friendly amenities."""
        score = green_space.recreation.playground_quality
        if green_space.environmental.shade_quality > 70:
            score += 20
        if green_space.accessibility.wheelchair_accessible:
            score += 10
        return min(100, score)
    
    async def _score_romantic_atmosphere(self, green_space: GreenSpace) -> int:
        """Score romantic atmosphere."""
        score = 0
        if green_space.environmental.water_features:
            score += 30
        if green_space.environmental.noise_level.value <= 2:
            score += 25
        score += green_space.environmental.tree_coverage_percent // 2
        score += green_space.accessibility.lighting_quality * 5
        return min(100, score)
    
    def _score_scenic_beauty(self, green_space: GreenSpace) -> int:
        """Score scenic beauty."""
        score = green_space.environmental.tree_coverage_percent
        if green_space.environmental.water_features:
            score += 20
        score += green_space.environmental.shade_quality // 2
        return min(100, score)
    
    async def _score_restaurant_proximity(self, green_space: GreenSpace) -> int:
        """Score restaurant proximity."""
        restaurants = [a for a in green_space.nearby_amenities 
                      if a.type in [AmenityType.RESTAURANT, AmenityType.CAFE]]
        if not restaurants:
            return 30
        closest_distance = min(r.distance_meters for r in restaurants)
        if closest_distance <= 200:
            return 100
        elif closest_distance <= 500:
            return 80
        else:
            return 60
    
    def _score_privacy(self, green_space: GreenSpace) -> int:
        """Score privacy based on size and tree coverage."""
        score = 0
        if green_space.area_sqm and green_space.area_sqm > 50000:
            score += 40
        elif green_space.area_sqm and green_space.area_sqm > 10000:
            score += 20
        score += green_space.environmental.tree_coverage_percent // 2
        return min(100, score)
    
    def _score_space_size(self, green_space: GreenSpace) -> int:
        """Score based on space size for groups."""
        if not green_space.area_sqm:
            return 50
        if green_space.area_sqm > 100000:
            return 100
        elif green_space.area_sqm > 50000:
            return 80
        elif green_space.area_sqm > 20000:
            return 60
        else:
            return 40
    
    async def _score_group_amenities(self, green_space: GreenSpace) -> int:
        """Score amenities suitable for groups."""
        score = 0
        if green_space.recreation.bbq_allowed:
            score += 30
        if green_space.recreation.sports_facilities:
            score += 25
        toilets = [a for a in green_space.nearby_amenities if a.type == AmenityType.TOILET]
        if toilets:
            score += 20
        score += green_space.accessibility.parking_availability * 5
        return min(100, score)
    
    async def _score_food_options(self, green_space: GreenSpace) -> int:
        """Score food options nearby."""
        food_amenities = [a for a in green_space.nearby_amenities 
                         if a.type in [AmenityType.RESTAURANT, AmenityType.CAFE, 
                                      AmenityType.ICE_CREAM, AmenityType.SPATI]]
        return min(100, len(food_amenities) * 25)
    
    def _score_activity_options(self, green_space: GreenSpace) -> int:
        """Score activity options."""
        score = 0
        if green_space.recreation.sports_facilities:
            score += 30
        if green_space.recreation.running_paths:
            score += 20
        if green_space.recreation.cycling_paths:
            score += 20
        if green_space.recreation.playground_quality > 0:
            score += 15
        if green_space.recreation.bbq_allowed:
            score += 15
        return min(100, score)
    
    def _score_quietness(self, green_space: GreenSpace) -> int:
        """Score quietness for zen seekers."""
        return (6 - green_space.environmental.noise_level.value) * 25
    
    def _score_nature_immersion(self, green_space: GreenSpace) -> int:
        """Score nature immersion."""
        score = green_space.environmental.tree_coverage_percent
        score += green_space.environmental.natural_surface_percent // 2
        if green_space.environmental.water_features:
            score += 15
        return min(100, score)
    
    async def _score_crowd_density(self, green_space: GreenSpace) -> int:
        """Score based on crowd density (lower crowds = higher score)."""
        # Mock implementation - in reality would use real-time data
        base_score = 70
        if green_space.area_sqm and green_space.area_sqm > 100000:
            base_score += 20
        if green_space.accessibility.public_transport_score <= 3:
            base_score += 10
        return min(100, base_score)
    
    def _score_meditation_spots(self, green_space: GreenSpace) -> int:
        """Score meditation spot quality."""
        score = green_space.environmental.tree_coverage_percent // 2
        if green_space.environmental.water_features:
            score += 25
        if green_space.environmental.noise_level.value <= 2:
            score += 25
        return min(100, score)
    
    def _score_air_quality(self, green_space: GreenSpace) -> int:
        """Score air quality."""
        score = green_space.environmental.tree_coverage_percent
        if green_space.environmental.natural_surface_percent > 80:
            score += 20
        return min(100, score)
    
    def _score_running_cycling_paths(self, green_space: GreenSpace) -> int:
        """Score running and cycling infrastructure."""
        score = 0
        if green_space.recreation.running_paths:
            score += 50
        if green_space.recreation.cycling_paths:
            score += 50
        return score
    
    def _score_sports_areas(self, green_space: GreenSpace) -> int:
        """Score sports areas."""
        return 100 if green_space.recreation.sports_facilities else 30
    
    def _score_terrain_variety(self, green_space: GreenSpace) -> int:
        """Score terrain variety for active users."""
        score = 50  # Base score
        if green_space.area_sqm and green_space.area_sqm > 50000:
            score += 30
        if green_space.environmental.natural_surface_percent > 70:
            score += 20
        return min(100, score)
    
    def _score_natural_habitat(self, green_space: GreenSpace) -> int:
        """Score natural habitat quality."""
        score = green_space.environmental.tree_coverage_percent
        score += green_space.environmental.natural_surface_percent // 2
        if green_space.environmental.water_features:
            score += 15
        return min(100, score)
    
    def _score_observation_spots(self, green_space: GreenSpace) -> int:
        """Score wildlife observation opportunities."""
        score = green_space.environmental.tree_coverage_percent // 2
        if green_space.environmental.water_features:
            score += 30
        if green_space.environmental.noise_level.value <= 2:
            score += 20
        return min(100, score)
    
    async def _score_cultural_proximity(self, green_space: GreenSpace) -> int:
        """Score proximity to cultural venues."""
        # Mock implementation - would check for nearby museums, galleries, etc.
        if green_space.neighborhood.lower() in ["mitte", "kreuzberg", "prenzlauer berg"]:
            return 80
        return 50
    
    async def _score_artistic_features(self, green_space: GreenSpace) -> int:
        """Score artistic features in the space."""
        # Mock implementation - would check for sculptures, installations, etc.
        return 60  # Base score
    
    async def _score_museum_accessibility(self, green_space: GreenSpace) -> int:
        """Score museum accessibility."""
        # Mock implementation
        if green_space.neighborhood.lower() == "mitte":
            return 90
        elif green_space.neighborhood.lower() in ["kreuzberg", "friedrichshain"]:
            return 70
        return 40
    
    def _score_creative_atmosphere(self, green_space: GreenSpace) -> int:
        """Score creative atmosphere."""
        score = 50  # Base score
        if green_space.environmental.tree_coverage_percent > 60:
            score += 20
        if green_space.environmental.water_features:
            score += 15
        if green_space.accessibility.lighting_quality >= 4:
            score += 15
        return min(100, score)
    
    async def _score_cafe_culture(self, green_space: GreenSpace) -> int:
        """Score cafe culture nearby."""
        cafes = [a for a in green_space.nearby_amenities if a.type == AmenityType.CAFE]
        return min(100, len(cafes) * 30 + 40)
    
    def _score_inspiring_views(self, green_space: GreenSpace) -> int:
        """Score inspiring views."""
        score = green_space.environmental.tree_coverage_percent // 2
        if green_space.environmental.water_features:
            score += 25
        if green_space.area_sqm and green_space.area_sqm > 50000:
            score += 25
        return min(100, score)
    
    async def _score_historical_significance(self, green_space: GreenSpace) -> int:
        """Score historical significance."""
        # Mock implementation - would check historical databases
        historical_neighborhoods = ["mitte", "kreuzberg", "charlottenburg"]
        if green_space.neighborhood.lower() in historical_neighborhoods:
            return 80
        return 40
    
    async def _score_monument_proximity(self, green_space: GreenSpace) -> int:
        """Score proximity to monuments."""
        # Mock implementation
        if green_space.neighborhood.lower() == "mitte":
            return 90
        return 50
    
    def _score_educational_value(self, green_space: GreenSpace) -> int:
        """Score educational value."""
        score = 50  # Base score
        if green_space.environmental.wildlife_diversity_score > 70:
            score += 25
        if green_space.environmental.water_features:
            score += 15
        if green_space.area_sqm and green_space.area_sqm > 100000:
            score += 10
        return min(100, score)
    
    def _score_architectural_features(self, green_space: GreenSpace) -> int:
        """Score architectural features."""
        # Mock implementation
        return 60
    
    async def _score_cultural_context(self, green_space: GreenSpace) -> int:
        """Score cultural context."""
        # Mock implementation
        cultural_neighborhoods = ["mitte", "kreuzberg", "prenzlauer berg", "friedrichshain"]
        if green_space.neighborhood.lower() in cultural_neighborhoods:
            return 75
        return 45
    
    def _create_explanation(self, personality: str, explanation_parts: List[str]) -> str:
        """Create a human-readable explanation."""
        if not explanation_parts:
            return f"This space has moderate appeal for {personality.replace('_', ' ')} personality type."
        
        return f"Great for {personality.replace('_', ' ')}: " + ", ".join(explanation_parts[:3])
    
    def _generate_recommendations(
        self, 
        green_space: GreenSpace, 
        personality: str, 
        component_scores: Dict[str, int]
    ) -> List[str]:
        """Generate personalized recommendations."""
        recommendations = []
        
        if personality == "little_adventurers":
            if green_space.recreation.playground_quality > 70:
                recommendations.append("Perfect playground for kids to explore")
            if green_space.environmental.shade_quality > 70:
                recommendations.append("Plenty of shade for family comfort")
        
        elif personality == "date_night":
            if green_space.environmental.water_features:
                recommendations.append("Romantic walks by the water")
            if component_scores.get("lighting_quality", 0) > 70:
                recommendations.append("Beautiful evening atmosphere")
        
        elif personality == "zen_masters":
            if component_scores.get("quietness", 0) > 80:
                recommendations.append("Perfect for meditation and reflection")
            if green_space.environmental.water_features:
                recommendations.append("Peaceful water sounds enhance tranquility")
        
        # Add generic recommendations if none specific
        if not recommendations:
            recommendations.append("Enjoy the natural beauty of this space")
            recommendations.append("Great for relaxation and outdoor activities")
        
        return recommendations
    
    async def score_location(
        self, 
        lat: float, 
        lng: float, 
        personality: str, 
        radius: int
    ) -> Dict[str, Any]:
        """Score a specific location with optimized performance."""
        # Check if location is in a green space
        green_space = await self.berlin_data.get_green_space_at_location(lat, lng)
        
        if not green_space:
            return {
                "score": 0,
                "explanation": "Location is not in a recognized green space",
                "location": {"lat": lat, "lng": lng},
                "personality": personality
            }
        
        # Score the green space (this now uses cached tree data internally)
        personality_score = await self.score_green_space(green_space, personality, (lat, lng))
        
        return {
            "score": personality_score.score,
            "explanation": personality_score.explanation,
            "location": {"lat": lat, "lng": lng},
            "personality": personality,
            "green_space": green_space.name,
            "recommendations": personality_score.recommendations
        }
    
    async def find_best_locations_within(
        self, 
        green_space: GreenSpace, 
        personality: str
    ) -> List[LocationScore]:
        """Find best locations within a green space."""
        # Mock implementation - in reality would analyze specific spots
        locations = []
        
        # Generate a few sample locations within the space
        base_lat, base_lng = green_space.coordinates.lat, green_space.coordinates.lng
        
        for i, (offset_lat, offset_lng, description) in enumerate([
            (0.001, 0.001, "Northeast corner with mature trees"),
            (-0.001, 0.001, "Southeast area near water feature"),
            (0.0, -0.001, "Western meadow area")
        ]):
            location = LocationScore(
                coordinates=Coordinates(
                    lat=base_lat + offset_lat,
                    lng=base_lng + offset_lng
                ),
                score=85 - i * 5,  # Decreasing scores
                explanation=f"Excellent spot: {description}",
                nearby_features=["trees", "seating", "paths"],
                best_for=[personality],
                recommendations=[f"Perfect for {personality.replace('_', ' ')} activities"]
            )
            locations.append(location)
        
        return locations
    
    # === ENHANCED TREE-BASED SCORING METHODS ===
    
    def _score_tree_coverage_with_real_data(self, green_space: GreenSpace, tree_data: Optional[Any] = None) -> int:
        """Enhanced tree coverage scoring using real street tree data."""
        if not tree_data:
            return green_space.environmental.tree_coverage_percent
        
        try:
            # Combine base environmental score with real tree data
            base_score = green_space.environmental.tree_coverage_percent
            tree_shade_coverage = tree_data.shade_analysis.estimated_shade_coverage
            
            # Use the higher of the two scores, with bonus for high tree density
            enhanced_score = max(base_score, tree_shade_coverage)
            
            # Bonus for high tree density
            if tree_data.metrics.trees_per_hectare > 50:
                enhanced_score = min(100, enhanced_score + 15)
            elif tree_data.metrics.trees_per_hectare > 20:
                enhanced_score = min(100, enhanced_score + 10)
            
            return int(enhanced_score)
            
        except Exception as e:
            print(f"Error enhancing tree coverage score: {e}")
            return green_space.environmental.tree_coverage_percent
    
    def _score_wildlife_diversity_with_trees(self, green_space: GreenSpace, tree_data: Optional[Any] = None) -> int:
        """Enhanced wildlife diversity scoring using real tree species data."""
        if not tree_data:
            return green_space.environmental.wildlife_diversity_score
        
        try:
            base_score = green_space.environmental.wildlife_diversity_score
            tree_diversity = tree_data.metrics.species_diversity_score
            mature_trees_bonus = min(20, tree_data.metrics.mature_trees_count)
            
            # Combine scores with weighting
            enhanced_score = int((base_score * 0.6) + (tree_diversity * 0.4) + mature_trees_bonus)
            
            return min(100, enhanced_score)
            
        except Exception as e:
            print(f"Error enhancing wildlife diversity score: {e}")
            return green_space.environmental.wildlife_diversity_score
    
    def _score_shade_quality_with_trees(self, green_space: GreenSpace, tree_data: Optional[Any] = None) -> int:
        """Enhanced shade quality scoring using real tree data."""
        if not tree_data:
            return green_space.environmental.shade_quality
        
        try:
            base_shade = green_space.environmental.shade_quality
            tree_shade_quality = tree_data.shade_analysis.shade_quality_score
            
            # Use the better of the two scores
            enhanced_score = max(base_shade, tree_shade_quality)
            
            # Bonus for large nearby trees
            large_trees_count = len(tree_data.shade_analysis.nearby_large_trees)
            if large_trees_count > 5:
                enhanced_score = min(100, enhanced_score + 15)
            elif large_trees_count > 2:
                enhanced_score = min(100, enhanced_score + 10)
            
            return int(enhanced_score)
            
        except Exception as e:
            print(f"Error enhancing shade quality score: {e}")
            return green_space.environmental.shade_quality
    
    def _score_nature_immersion_with_trees(self, green_space: GreenSpace, tree_data: Optional[Any] = None) -> int:
        """Enhanced nature immersion scoring using real tree data."""
        if not tree_data:
            return self._score_nature_immersion(green_space)
        
        try:
            # Base score from existing method
            base_score = green_space.environmental.tree_coverage_percent
            base_score += green_space.environmental.natural_surface_percent // 2
            if green_space.environmental.water_features:
                base_score += 15
            
            # Enhancement from tree data
            tree_density_score = min(30, tree_data.metrics.trees_per_hectare)
            canopy_density_bonus = int(tree_data.shade_analysis.canopy_density * 20) if tree_data.shade_analysis.canopy_density else 0
            species_diversity_bonus = min(15, tree_data.metrics.species_diversity_score // 5)
            
            enhanced_score = base_score + tree_density_score + canopy_density_bonus + species_diversity_bonus
            
            return min(100, int(enhanced_score))
            
        except Exception as e:
            print(f"Error enhancing nature immersion score: {e}")
            return self._score_nature_immersion(green_space)
    
    def _score_natural_habitat_with_trees(self, green_space: GreenSpace, tree_data: Optional[Any] = None) -> int:
        """Enhanced natural habitat scoring using real tree data."""
        if not tree_data:
            return self._score_natural_habitat(green_space)
        
        try:
            base_score = green_space.environmental.tree_coverage_percent
            base_score += green_space.environmental.natural_surface_percent // 2
            if green_space.environmental.water_features:
                base_score += 15
            
            # Tree habitat quality factors
            mature_trees_score = min(25, tree_data.metrics.mature_trees_count // 2)
            species_diversity_score = min(20, tree_data.metrics.species_diversity_score // 3)
            
            enhanced_score = base_score + mature_trees_score + species_diversity_score
            
            return min(100, int(enhanced_score))
            
        except Exception as e:
            print(f"Error enhancing natural habitat score: {e}")
            return self._score_natural_habitat(green_space)
    
    def _score_observation_spots_with_trees(self, green_space: GreenSpace, tree_data: Optional[Any] = None) -> int:
        """Enhanced wildlife observation scoring using real tree data."""
        if not tree_data:
            return self._score_observation_spots(green_space)
        
        try:
            base_score = green_space.environmental.tree_coverage_percent // 2
            if green_space.environmental.water_features:
                base_score += 30
            if green_space.environmental.noise_level.value <= 2:
                base_score += 20
            
            # Large trees provide better observation opportunities
            large_trees_count = len(tree_data.shade_analysis.nearby_large_trees)
            observation_bonus = min(25, large_trees_count * 3)
            
            # Species diversity attracts more wildlife to observe
            diversity_bonus = min(15, tree_data.metrics.species_diversity_score // 4)
            
            enhanced_score = base_score + observation_bonus + diversity_bonus
            
            return min(100, int(enhanced_score))
            
        except Exception as e:
            print(f"Error enhancing observation spots score: {e}")
            return self._score_observation_spots(green_space)
    
    def _score_meditation_spots_with_trees(self, green_space: GreenSpace, tree_data: Optional[Any] = None) -> int:
        """Enhanced meditation spots scoring using real tree data."""
        if not tree_data:
            return self._score_meditation_spots(green_space)
        
        try:
            base_score = green_space.environmental.tree_coverage_percent // 2
            if green_space.environmental.water_features:
                base_score += 25
            if green_space.environmental.noise_level.value <= 2:
                base_score += 25
            
            # Trees enhance meditation through natural sounds and shade
            shade_quality_bonus = min(20, tree_data.shade_analysis.shade_quality_score // 4)
            canopy_bonus = int(tree_data.shade_analysis.canopy_density * 15) if tree_data.shade_analysis.canopy_density else 0
            
            enhanced_score = base_score + shade_quality_bonus + canopy_bonus
            
            return min(100, int(enhanced_score))
            
        except Exception as e:
            print(f"Error enhancing meditation spots score: {e}")
            return self._score_meditation_spots(green_space)
    
    def _score_air_quality_with_trees(self, green_space: GreenSpace, tree_data: Optional[Any] = None) -> int:
        """Enhanced air quality scoring using real tree data."""
        if not tree_data:
            return self._score_air_quality(green_space)
        
        try:
            base_score = green_space.environmental.tree_coverage_percent
            if green_space.environmental.natural_surface_percent > 80:
                base_score += 20
            
            # More trees = better air quality
            tree_density_bonus = min(25, tree_data.metrics.trees_per_hectare // 2)
            mature_trees_bonus = min(15, tree_data.metrics.mature_trees_count // 3)
            
            enhanced_score = base_score + tree_density_bonus + mature_trees_bonus
            
            return min(100, int(enhanced_score))
            
        except Exception as e:
            print(f"Error enhancing air quality score: {e}")
            return self._score_air_quality(green_space)
