# app/routers/green_spaces.py
from fastapi import APIRouter, Query, HTTPException
from typing import Optional, List
from enum import Enum

from app.models.green_space import ScoringRequest
from app.models.response import GreenSpaceResponse, NearbyAmenitiesResponse
from app.services.green_space_service import GreenSpaceService
from app.services.berlin_data_service import BerlinDataService

router = APIRouter(prefix="/green-spaces", tags=["green-spaces"])

# Services
green_space_service = GreenSpaceService()
berlin_data = BerlinDataService()

class PersonalityType(str, Enum):
    LITTLE_ADVENTURERS = "little_adventurers"
    DATE_NIGHT = "date_night"
    SQUAD_GOALS = "squad_goals"
    ZEN_MASTERS = "zen_masters"
    ACTIVE_LIFESTYLE = "active_lifestyle"
    WILDLIFE_LOVER = "wildlife_lover"
    ART_NERD = "art_nerd"
    HISTORY_GEEK = "history_geek"

@router.get("/search", response_model=GreenSpaceResponse)
async def search_green_spaces(
    # Location filters
    lat: Optional[float] = Query(None, description="Latitude for location-based search"),
    lng: Optional[float] = Query(None, description="Longitude for location-based search"),
    radius: int = Query(2000, ge=100, le=10000, description="Search radius in meters"),
    
    # Area filters
    neighborhood: Optional[str] = Query(None, description="Berlin neighborhood"),
    
    # Personality scoring
    personality: PersonalityType = Query(..., description="Personality type for scoring"),
    min_score: int = Query(60, ge=0, le=100, description="Minimum personality score"),
    
    # Feature filters
    min_size: Optional[int] = Query(None, ge=100, description="Minimum area in square meters"),
    has_water: Optional[bool] = Query(None, description="Must have water features"),
    has_playground: Optional[bool] = Query(None, description="Must have playground nearby"),
    max_noise_level: Optional[int] = Query(None, ge=1, le=5, description="Maximum noise level"),
    
    # Response options
    limit: int = Query(20, ge=1, le=100, description="Maximum results"),
    include_amenities: bool = Query(False, description="Include detailed amenity data"),
):
    """
    Search for green spaces in Berlin and score them for a personality type.
    
    This endpoint dynamically analyzes Berlin's green spaces and scores them
    based on the selected personality preferences.
    """
    try:
        # Build search request
        search_request = ScoringRequest(
            personality=personality.value,
            location=(lat, lng) if lat and lng else None,
            radius=radius,
            neighborhood=neighborhood,
            min_score=min_score,
            filters={
                "min_size": min_size,
                "has_water": has_water,
                "has_playground": has_playground,
                "max_noise_level": max_noise_level,
            },
            limit=limit,
            include_amenities=include_amenities
        )
        
        # Get and score green spaces
        results = await green_space_service.search_and_score(search_request)
        
        return GreenSpaceResponse(
            green_spaces=results,
            total_found=len(results),
            search_params=search_request.dict(),
            personality=personality.value
        )
        
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Search failed: {str(e)}")

@router.get("/score-location")
async def score_specific_location(
    lat: float = Query(..., description="Latitude of location to score"),
    lng: float = Query(..., description="Longitude of location to score"),
    personality: PersonalityType = Query(..., description="Personality type"),
    radius: int = Query(300, ge=50, le=1000, description="Analysis radius in meters"),
):
    """
    Score a specific location for a personality type.
    
    Analyzes the immediate area around the given coordinates and provides
    a personality-based score with detailed explanations.
    """
    try:
        # Check if location is in a green space
        green_space = await 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.value
            }
        
        # Score the location
        from app.services.scoring_engine import ScoringEngine
        scoring_engine = ScoringEngine()
        score_result = await scoring_engine.score_location(
            lat, lng, personality.value, radius
        )
        
        return score_result
        
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Scoring failed: {str(e)}")

@router.get("/discover")
async def discover_green_spaces(
    lat: float = Query(..., description="Your current latitude"),
    lng: float = Query(..., description="Your current longitude"),
    max_distance: int = Query(5000, ge=500, le=20000, description="Maximum distance in meters"),
    personality: PersonalityType = Query(..., description="Your personality type"),
):
    """
    Discover highly-rated green spaces near your location.
    
    Returns the best green spaces within walking/cycling distance,
    scored for your personality type.
    """
    try:
        discoveries = await green_space_service.discover_nearby(
            lat, lng, max_distance, personality.value
        )
        
        return {
            "discoveries": discoveries,
            "your_location": {"lat": lat, "lng": lng},
            "search_radius": max_distance,
            "personality": personality.value
        }
        
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Discovery failed: {str(e)}")

@router.get("/{space_id}/analysis")
async def analyze_green_space(
    space_id: str,
    personality: Optional[PersonalityType] = Query(None, description="Personality for focused analysis"),
):
    """
    Get detailed analysis of a specific green space.
    
    Provides comprehensive scoring across all personalities or
    focused analysis for a specific personality type.
    """
    try:
        analysis = await green_space_service.get_detailed_analysis(
            space_id, personality.value if personality else None
        )
        
        if not analysis:
            raise HTTPException(status_code=404, detail="Green space not found")
            
        return analysis
        
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Analysis failed: {str(e)}")

@router.get("/conditions")
async def get_current_conditions(
    lat: float = Query(..., description="Latitude"),
    lng: float = Query(..., description="Longitude"),
):
    """Get current conditions at a green space (weather, crowds, etc.)."""
    try:
        conditions = await berlin_data.get_current_conditions(lat, lng)
        return conditions
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Failed to get conditions: {str(e)}")

@router.get("/all")
async def get_all_green_spaces(
    personality: Optional[PersonalityType] = Query(None, description="Personality type for scoring"),
    min_score: int = Query(0, ge=0, le=100, description="Minimum personality score (only applies if personality is provided)"),
    limit: int = Query(50, ge=1, le=200, description="Maximum results"),
):
    """
    Get all available green spaces in Berlin.
    
    Optionally score them for a specific personality type.
    Perfect for frontend dropdowns or full dataset access.
    """
    try:
        # Get all green spaces
        all_spaces = await berlin_data.search_green_spaces()
        
        # If personality is specified, score and filter
        if personality:
            scored_spaces = []
            for space in all_spaces:
                personality_score = await green_space_service.scoring_engine.score_green_space(
                    space, personality.value
                )
                
                if personality_score.score >= min_score:
                    space.current_personality_score = personality_score
                    scored_spaces.append(space)
            
            # Sort by score (highest first)
            scored_spaces.sort(
                key=lambda x: x.current_personality_score.score if x.current_personality_score else 0,
                reverse=True
            )
            all_spaces = scored_spaces
        
        # Apply limit
        limited_spaces = all_spaces[:limit]
        
        return {
            "green_spaces": limited_spaces,
            "total_available": len(all_spaces),
            "returned_count": len(limited_spaces),
            "personality": personality.value if personality else None,
            "min_score_applied": min_score if personality else None
        }
        
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Failed to get green spaces: {str(e)}")

@router.get("/recommendations/{personality}")
async def get_personality_recommendations(
    personality: PersonalityType,
    limit: int = Query(20, ge=1, le=50, description="Number of recommendations"),
    neighborhood: Optional[str] = Query(None, description="Preferred neighborhood"),
    min_score: int = Query(70, ge=50, le=100, description="Minimum personality score"),
):
    """
    Get personalized green space recommendations.
    
    Returns the best green spaces for a specific personality type,
    with explanations of why each space is recommended.
    """
    try:
        # Get all green spaces
        all_spaces = await berlin_data.search_green_spaces(neighborhood=neighborhood)
        
        # Score and rank for personality
        recommendations = []
        for space in all_spaces:
            personality_score = await green_space_service.scoring_engine.score_green_space(
                space, personality.value
            )
            
            if personality_score.score >= min_score:
                space.current_personality_score = personality_score
                
                # Get additional insights
                best_features = []
                if space.environmental.tree_coverage_percent > 70:
                    best_features.append("Excellent tree coverage")
                if space.environmental.water_features:
                    best_features.append("Water features")
                if space.recreation.playground_quality > 60:
                    best_features.append("Good playground facilities")
                if space.recreation.sports_facilities:
                    best_features.append("Sports facilities")
                if space.environmental.noise_level.value <= 2:
                    best_features.append("Peaceful atmosphere")
                
                recommendation = {
                    "green_space": space,
                    "score": personality_score.score,
                    "explanation": personality_score.explanation,
                    "best_features": best_features[:3],  # Top 3 features
                    "visit_recommendation": _get_visit_recommendation(space, personality.value)
                }
                recommendations.append(recommendation)
        
        # Sort by score
        recommendations.sort(key=lambda x: x["score"], reverse=True)
        
        return {
            "recommendations": recommendations[:limit],
            "personality": personality.value,
            "total_matches": len(recommendations),
            "search_filters": {
                "neighborhood": neighborhood,
                "min_score": min_score
            }
        }
        
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Failed to get recommendations: {str(e)}")

def _get_visit_recommendation(space, personality: str) -> str:
    """Get a personalized visit recommendation"""
    if personality == "little_adventurers":
        if space.recreation.playground_quality > 60:
            return "Perfect for family adventures with great playground facilities"
        return "Great for exploring with kids"
    elif personality == "date_night":
        if space.environmental.noise_level.value <= 2:
            return "Romantic and peaceful setting for couples"
        return "Nice atmosphere for a romantic stroll"
    elif personality == "zen_masters":
        if space.environmental.tree_coverage_percent > 70:
            return "Ideal for peaceful meditation under the trees"
        return "Perfect for quiet contemplation"
    elif personality == "active_lifestyle":
        if space.recreation.sports_facilities:
            return "Great for workouts and active recreation"
        return "Perfect for running and outdoor activities"
    elif personality == "wildlife_lover":
        if space.environmental.wildlife_diversity_score > 70:
            return "Excellent biodiversity for nature observation"
        return "Good spot for wildlife watching"
    else:
        return "Highly recommended for your personality type"
