from typing import Optional, List, Any
from datetime import datetime
from uuid import UUID
from pydantic import BaseModel, model_validator


class TributeResponse(BaseModel):
    id: UUID
    memorial_id: UUID
    submitter_name: str
    submitter_email: Optional[str] = None
    relationship: Optional[str] = None
    message: str
    photo_url: Optional[str] = None
    status: str
    submitted_at: datetime
    moderated_at: Optional[datetime] = None

    model_config = {"from_attributes": True}


class TimelineEventResponse(BaseModel):
    id: UUID
    year: int
    title: str
    description: Optional[str] = None
    sort_order: int = 0

    model_config = {"from_attributes": True}

    @model_validator(mode="before")
    @classmethod
    def compute_year_from_event_date(cls, values: Any) -> Any:
        if isinstance(values, dict):
            # Dict path: derive year from event_date if year key is absent
            if not values.get("year"):
                event_date = values.get("event_date")
                if event_date is not None:
                    if isinstance(event_date, datetime):
                        values["year"] = event_date.year
                    elif hasattr(event_date, "year"):
                        values["year"] = event_date.year
            return values

        # ORM object path: pull year from event_date when year attribute is unset
        year = getattr(values, "year", None)
        if year is None:
            event_date = getattr(values, "event_date", None)
            if event_date is not None:
                extracted = event_date.year if isinstance(event_date, datetime) else getattr(event_date, "year", None)
                if extracted is not None:
                    try:
                        object.__setattr__(values, "year", extracted)
                    except (AttributeError, TypeError):
                        pass
        return values


class MemorialForRecordResponse(BaseModel):
    id: UUID
    slug: str
    display_name: Optional[str] = None
    is_published: bool
    published_at: Optional[datetime] = None
    created_at: datetime
    updated_at: datetime
    photo_count: int = 0
    tribute_count: int = 0

    model_config = {"from_attributes": True}

    @model_validator(mode="before")
    @classmethod
    def compute_counts(cls, values: Any) -> Any:
        if isinstance(values, dict):
            return values

        # ORM object — compute counts from relationships if not already set
        if not hasattr(values, "__dict__"):
            return values

        obj_dict = values.__dict__

        # photo_count: length of photos relationship
        if "photo_count" not in obj_dict or obj_dict.get("photo_count") is None:
            photos = getattr(values, "photos", None)
            if photos is not None:
                try:
                    object.__setattr__(values, "photo_count", len(photos))
                except (AttributeError, TypeError):
                    pass

        # tribute_count: count approved tributes
        if "tribute_count" not in obj_dict or obj_dict.get("tribute_count") is None:
            tributes = getattr(values, "tributes", None)
            if tributes is not None:
                try:
                    approved = [t for t in tributes if getattr(t, "status", None) == "approved"]
                    object.__setattr__(values, "tribute_count", len(approved))
                except (AttributeError, TypeError):
                    pass

        return values


class MemorialSummaryResponse(BaseModel):
    id: UUID
    record_id: UUID
    slug: str
    display_name: Optional[str] = None
    headstone_inscription: Optional[str] = None
    biography_text: Optional[str] = None
    ai_biography_text: Optional[str] = None
    video_url: Optional[str] = None
    visibility_config: Optional[Any] = None
    is_published: bool
    published_at: Optional[datetime] = None
    created_at: datetime
    updated_at: datetime

    model_config = {"from_attributes": True}


class MemorialResponse(MemorialSummaryResponse):
    tributes: List[TributeResponse] = []
    timeline_events: List[TimelineEventResponse] = []
