from pydantic import BaseModel, EmailStr, Field, field_validator, ConfigDict
from datetime import datetime
from typing import Annotated
from pydantic import BeforeValidator

StrId = Annotated[str, BeforeValidator(str)]


class SubmissionBase(BaseModel):
    name: str = Field(..., min_length=2, max_length=100)
    email: EmailStr = Field(..., max_length=255)

    @field_validator("name")
    @classmethod
    def validate_name(cls, v: str) -> str:
        v = v.strip()
        if len(v) < 2:
            raise ValueError("Name must contain at least 2 characters")
        if len(v) > 100:
            raise ValueError("Name cannot exceed 100 characters")
        return v

    @field_validator("email")
    @classmethod
    def validate_email(cls, v: str) -> str:
        v = v.strip().lower()
        if len(v) > 255:
            raise ValueError("Email cannot exceed 255 characters")
        return v


class SubmissionCreate(SubmissionBase):
    pass


class SubmissionUpdate(BaseModel):
    name: str | None = Field(None, min_length=2, max_length=100)
    email: EmailStr | None = Field(None, max_length=255)

    @field_validator("name")
    @classmethod
    def validate_name(cls, v: str | None) -> str | None:
        if v is None:
            return v
        v = v.strip()
        if len(v) < 2:
            raise ValueError("Name must contain at least 2 characters")
        if len(v) > 100:
            raise ValueError("Name cannot exceed 100 characters")
        return v

    @field_validator("email")
    @classmethod
    def validate_email(cls, v: str | None) -> str | None:
        if v is None:
            return v
        v = v.strip().lower()
        if len(v) > 255:
            raise ValueError("Email cannot exceed 255 characters")
        return v


class SubmissionResponse(SubmissionBase):
    id: StrId
    created_at: datetime
    updated_at: datetime

    model_config = ConfigDict(from_attributes=True)


class PaginatedSubmissionResponse(BaseModel):
    items: list[SubmissionResponse]
    total: int
    limit: int
    offset: int

    model_config = ConfigDict(from_attributes=True)