from typing import Optional, List, Dict, Any, Annotated
from pydantic import BaseModel, Field, ConfigDict, field_validator, BeforeValidator
from datetime import datetime

StrId = Annotated[str, BeforeValidator(str)]


class ReportBase(BaseModel):
    name: str = Field(..., max_length=255)
    description: Optional[str] = None
    report_type: str = Field(..., max_length=100)
    parameters: Dict[str, Any] = Field(default_factory=dict)
    file_path: Optional[str] = Field(None, max_length=1000)
    export_format: Optional[str] = Field(None, max_length=50)
    generated_at: Optional[datetime] = None

    @field_validator("name", "report_type")
    @classmethod
    def strip_whitespace(cls, v):
        if v is None:
            return v
        return v.strip()

    @field_validator("description", "file_path", "export_format")
    @classmethod
    def strip_optional_whitespace(cls, v):
        if v is None:
            return v
        return v.strip()


class ReportCreate(ReportBase):
    generated_by_user_id: str = Field(..., max_length=36)


class ReportUpdate(BaseModel):
    name: Optional[str] = Field(None, max_length=255)
    description: Optional[str] = None
    report_type: Optional[str] = Field(None, max_length=100)
    parameters: Optional[Dict[str, Any]] = None
    file_path: Optional[str] = Field(None, max_length=1000)
    export_format: Optional[str] = Field(None, max_length=50)
    generated_at: Optional[datetime] = None

    @field_validator("name", "report_type")
    @classmethod
    def strip_whitespace(cls, v):
        if v is None:
            return v
        return v.strip()

    @field_validator("description", "file_path", "export_format")
    @classmethod
    def strip_optional_whitespace(cls, v):
        if v is None:
            return v
        return v.strip()


class ReportResponse(ReportBase):
    id: StrId
    generated_by_user_id: StrId
    created_at: datetime
    updated_at: datetime

    model_config = ConfigDict(from_attributes=True)


class GeneratedByUserSummary(BaseModel):
    id: StrId
    first_name: str
    last_name: str
    email: str

    model_config = ConfigDict(from_attributes=True)


class ReportDetailResponse(ReportResponse):
    generated_by_user: GeneratedByUserSummary

    model_config = ConfigDict(from_attributes=True)


class ReportListResponse(BaseModel):
    items: List[ReportResponse]
    total: int
    limit: int
    offset: int

    model_config = ConfigDict(from_attributes=True)