from __future__ import annotations from datetime import datetime from typing import Any from pydantic import BaseModel, ConfigDict, Field class CaseBase(BaseModel): model_config = ConfigDict(extra='allow') age: int | None = None age_years: int | None = None gender: str | None = None child_name: str | None = None height_build: str | None = None clothes_upper: str | None = None clothes_lower: str | None = None clothes_shoes: str | None = None shoes: str | None = None clothes_description: str | None = None special_marks: str | None = None phone_status: str | None = None health_flags: list[str] = Field(default_factory=list) has_diagnosis: bool | None = None diagnosis_type: list[str] = Field(default_factory=list) fitness_level: str | None = None has_transport: str | None = None cant_swim: bool | None = None psychotype: str | None = None psychotype_answers: dict[str, Any] | None = None elapsed_hours: float | None = None last_known_place: str | None = None direction: str | None = None reason: str | None = None loss_reason: str | None = None loss_time: datetime | None = None last_seen_direction: str | None = None last_seen_reliability: str | None = None last_seen_description: str | None = None behavior_description: str | None = None familiar_places: str | None = None lost_before: str | None = None terrain_primary: str | None = None terrain: list[str] = Field(default_factory=list) weather: str | None = None season: str | None = None temperature_c: float | None = None precipitation: str | None = None visibility: str | None = None wind: str | None = None gps: dict[str, float] | None = None gps_lat: float | None = None gps_lon: float | None = None tnp_lat: float | None = None tnp_lon: float | None = None tnp_address: str | None = None resources: list[str] = Field(default_factory=list) teams_count: int | None = None team_size: int | None = None has_dog: bool | None = None extra_resources: list[str] = Field(default_factory=list) notes: str | None = None note: str | None = None status: str | None = None found_alive: bool | None = None found_distance_km: float | None = None found_direction: str | None = None found_location_type: str | None = None found_lat: float | None = None found_lon: float | None = None search_duration_hours: float | None = None who_found: str | None = None raw_text: str | None = None analysis_log: dict[str, Any] | None = None mobile: bool = False class CaseCreate(CaseBase): status: str | None = 'new' class CaseUpdate(CaseBase): pass class CaseResponse(CaseBase): id: str created_at: datetime updated_at: datetime status: str health_flags: list[str] = Field(default_factory=list) diagnosis_type: list[str] = Field(default_factory=list) terrain: list[str] = Field(default_factory=list) resources: list[str] = Field(default_factory=list) extra_resources: list[str] = Field(default_factory=list) result: dict[str, Any] | None = None class CaseListResponse(BaseModel): items: list[CaseResponse] total: int page: int page_size: int class DashboardResponse(BaseModel): total_cases: int found_alive_count: int found_deceased_count: int unknown_outcome_count: int median_found_distance_km: float | None recent_activity_count: int class RecommendationRequest(BaseModel): age: int | None = None gender: str | None = None health_flags: list[str] = Field(default_factory=list) elapsed_hours: int | None = None terrain_primary: str | None = None weather: str | None = None resources: list[str] = Field(default_factory=list) class AnalyzeResponse(BaseModel): urgency: str primary_zones: list[dict[str, Any]] immediate_actions: list[str] behavioral_prediction: str psychotype_recommendations: dict[str, Any] key_locations: list[str] case_id: str class ParseDocResponse(BaseModel): filename: str parsed: bool preview: dict[str, Any] raw_text: str | None = None