from typing import Optional, Dict, Any, Annotated
from pydantic import BaseModel, Field, ConfigDict, field_validator, model_validator, BeforeValidator
from datetime import date, datetime
from utils.utils import ReportType, ReportStatus

StrId = Annotated[str, BeforeValidator(str)]


class ReportBase(BaseModel):
    report_name: str = Field(..., max_length=200)
    report_type: ReportType
    generated_by_user_id: str = Field(..., max_length=36)
    start_date: Optional[date] = None
    end_date: Optional[date] = None
    parameters: Optional[Dict[str, Any]] = None
    file_path: Optional[str] = Field(None, max_length=500)
    status: ReportStatus
    generated_at: Optional[datetime] = None

    @field_validator("report_name")
    @classmethod
    def validate_report_name(cls, v):
        if v is not None:
            v = v.strip()
            if not v:
                raise ValueError("report_name cannot be empty")
        return v

    @field_validator("file_path")
    @classmethod
    def validate_file_path(cls, v):
        if v is not None:
            v = v.strip()
        return v

    @model_validator(mode="after")
    def check_date_range(self):
        if self.end_date and self.start_date and self.end_date < self.start_date:
            raise ValueError("end_date must be on or after start_date")
        return self


class ReportCreate(ReportBase):
    pass


class ReportUpdate(BaseModel):
    report_name: Optional[str] = Field(None, max_length=200)
    report_type: Optional[ReportType] = None
    generated_by_user_id: Optional[str] = Field(None, max_length=36)
    start_date: Optional[date] = None
    end_date: Optional[date] = None
    parameters: Optional[Dict[str, Any]] = None
    file_path: Optional[str] = Field(None, max_length=500)
    status: Optional[ReportStatus] = None
    generated_at: Optional[datetime] = None

    @field_validator("report_name")
    @classmethod
    def validate_report_name(cls, v):
        if v is not None:
            v = v.strip()
            if not v:
                raise ValueError("report_name cannot be empty")
        return v

    @field_validator("file_path")
    @classmethod
    def validate_file_path(cls, v):
        if v is not None:
            v = v.strip()
        return v

    @model_validator(mode="after")
    def check_date_range(self):
        if self.end_date is not None and self.start_date is not None and self.end_date < self.start_date:
            raise ValueError("end_date must be on or after start_date")
        return self


class ReportResponse(BaseModel):
    id: StrId
    report_name: str
    report_type: ReportType
    generated_by_user_id: StrId
    start_date: Optional[date]
    end_date: Optional[date]
    parameters: Optional[Dict[str, Any]]
    file_path: Optional[str]
    status: ReportStatus
    generated_at: Optional[datetime]
    created_at: datetime
    updated_at: datetime

    model_config = ConfigDict(from_attributes=True)


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

    model_config = ConfigDict(from_attributes=True)


class ReportDetailResponse(BaseModel):
    id: StrId
    report_name: str
    report_type: ReportType
    generated_by_user_id: StrId
    start_date: Optional[date]
    end_date: Optional[date]
    parameters: Optional[Dict[str, Any]]
    file_path: Optional[str]
    status: ReportStatus
    generated_at: Optional[datetime]
    created_at: datetime
    updated_at: datetime
    generated_by: Optional[UserSummary]

    model_config = ConfigDict(from_attributes=True)


class PaginatedReportResponse(BaseModel):
    items: list[ReportResponse]
    total: int
    limit: int
    offset: int

    model_config = ConfigDict(from_attributes=True)