from pydantic import BaseModel, Field
from typing import Optional, List, Dict, Any
from datetime import datetime
from enum import Enum

from .green_space import Coordinates

class TreeCategory(str, Enum):
    STREET_TREE = "street_tree"
    PARK_TREE = "park_tree"
    ANLAGEBAUM = "anlagebaum"
    ALLEE_TREE = "allee_tree"

class TreeHealthStatus(str, Enum):
    EXCELLENT = "excellent"
    GOOD = "good"
    FAIR = "fair"
    POOR = "poor"
    CRITICAL = "critical"
    UNKNOWN = "unknown"

class TreeGenus(str, Enum):
    AHORN = "ahorn"
    LINDE = "linde"
    KASTANIE = "kastanie"
    EICHE = "eiche"
    PLATANE = "platane"
    BIRKE = "birke"
    WEISSDORN = "weissdorn"
    ROSSKASTANIE = "rosskastanie"
    PAPPEL = "pappel"
    ESCHE = "esche"
    OTHER = "other"

class StreetTree(BaseModel):
    """Individual street tree model based on Berlin Baumkataster data."""
    
    id: str
    object_id: Optional[int] = None
    tree_id: Optional[str] = None
    location_number: Optional[str] = None
    identifier: Optional[str] = None
    
    object_name: Optional[str] = None
    species_german: Optional[str] = None
    species_botanical: Optional[str] = None
    genus_german: Optional[str] = None
    genus_botanical: Optional[str] = None
    genus_category: Optional[TreeGenus] = None
    
    coordinates: Coordinates
    district: Optional[str] = None
    owner: Optional[str] = None
    category: Optional[str] = None
    
    street: Optional[str] = None
    house_number: Optional[str] = None
    address_addition: Optional[str] = None
    full_address: Optional[str] = None
    
    planting_year: Optional[int] = None
    age: Optional[int] = None
    crown_diameter_m: Optional[float] = None
    trunk_circumference_cm: Optional[int] = None
    height_m: Optional[float] = None
    
    health_status: TreeHealthStatus = TreeHealthStatus.UNKNOWN
    confidence_score: int = Field(80, ge=0, le=100)
    
    last_updated: datetime = Field(default_factory=datetime.now)

class TreeDensityMetrics(BaseModel):
    """Tree density and coverage metrics for an area."""
    
    total_trees: int = 0
    trees_per_hectare: float = 0.0
    average_tree_age: Optional[float] = None
    average_height: Optional[float] = None
    average_crown_diameter: Optional[float] = None
    
    shade_coverage_percent: float = Field(0.0, ge=0, le=100)
    mature_trees_count: int = 0  # Trees older than 20 years
    young_trees_count: int = 0   # Trees younger than 10 years
    
    dominant_species: List[str] = []
    species_diversity_score: int = Field(0, ge=0, le=100)
    
class TreeShadeAnalysis(BaseModel):
    """Shade analysis for picnic spot evaluation."""
    
    has_nearby_trees: bool = False
    trees_within_50m: int = 0
    trees_within_100m: int = 0
    
    estimated_shade_coverage: int = Field(0, ge=0, le=100)
    shade_quality_score: int = Field(0, ge=0, le=100)
    
    best_shade_times: List[str] = []  # Time periods with best shade
    seasonal_shade_variation: Optional[str] = None
    
    nearby_large_trees: List[StreetTree] = []
    canopy_density: Optional[float] = None

class TreesSearchFilters(BaseModel):
    """Filters for searching trees."""
    
    species: Optional[List[str]] = None
    genus: Optional[List[TreeGenus]] = None
    min_age: Optional[int] = None
    max_age: Optional[int] = None
    min_height: Optional[float] = None
    max_height: Optional[float] = None
    min_crown_diameter: Optional[float] = None
    district: Optional[str] = None
    category: Optional[str] = None
    
    within_radius_m: Optional[int] = None
    center_lat: Optional[float] = None
    center_lng: Optional[float] = None

class TreesNearLocationResponse(BaseModel):
    """Response for trees near a location query."""
    
    location: Coordinates
    radius_m: int
    trees: List[StreetTree]
    metrics: TreeDensityMetrics
    shade_analysis: TreeShadeAnalysis
    
    total_found: int
    query_time_ms: Optional[int] = None
    data_source: str = "baumkataster"
    last_updated: datetime = Field(default_factory=datetime.now)