from datetime import datetime
from enum import Enum
from typing import Optional
from uuid import UUID

from pydantic import BaseModel, ConfigDict, Field, model_validator


class UploadSessionStatus(str, Enum):
    INITIATED = "initiated"
    UPLOADING = "uploading"
    PROCESSING = "processing"
    COMPLETED = "completed"
    FAILED = "failed"
    EXPIRED = "expired"
    CANCELED = "canceled"


class UploadSessionBase(BaseModel):
    user_id: int
    filename: str
    mime_type: str
    total_size_bytes: int = Field(gt=0)
    uploaded_size_bytes: int = Field(default=0, ge=0)
    status: UploadSessionStatus = UploadSessionStatus.INITIATED
    s3_multipart_upload_id: Optional[str] = None
    s3_object_key: Optional[str] = None
    failure_reason: Optional[str] = None
    expires_at: datetime
    completed_at: Optional[datetime] = None

    @model_validator(mode="after")
    def validate_progress(self) -> "UploadSessionBase":
        if self.uploaded_size_bytes > self.total_size_bytes:
            raise ValueError("uploaded_size_bytes cannot exceed total_size_bytes")
        return self


class UploadSessionCreate(UploadSessionBase):
    id: UUID


class UploadSessionUpdate(BaseModel):
    uploaded_size_bytes: Optional[int] = Field(default=None, ge=0)
    status: Optional[UploadSessionStatus] = None
    s3_multipart_upload_id: Optional[str] = None
    s3_object_key: Optional[str] = None
    failure_reason: Optional[str] = None
    completed_at: Optional[datetime] = None


class UploadSession(UploadSessionBase):
    id: UUID
    created_at: datetime
    updated_at: datetime

    model_config = ConfigDict(from_attributes=True)
