"""Auth + user schemas."""
from pydantic import BaseModel, ConfigDict, Field, field_validator

from app.models.enums import UserRole
from app.schemas.types import DhakaDateTime, InternalEmail

PASSWORD_MIN = 8


def _validate_password(value: str) -> str:
    if len(value) < PASSWORD_MIN:
        raise ValueError(f"password must be at least {PASSWORD_MIN} characters")
    if not any(c.isalpha() for c in value):
        raise ValueError("password must contain a letter")
    if not any(c.isdigit() for c in value):
        raise ValueError("password must contain a digit")
    return value


# --- Auth ---


class LoginRequest(BaseModel):
    email: InternalEmail
    password: str


class TokenPair(BaseModel):
    access_token: str
    refresh_token: str
    token_type: str = "bearer"
    expires_in: int = Field(description="Access-token lifetime in seconds.")


class RefreshRequest(BaseModel):
    refresh_token: str


class ChangePasswordRequest(BaseModel):
    current_password: str
    new_password: str

    @field_validator("new_password")
    @classmethod
    def check_new(cls, v: str) -> str:
        return _validate_password(v)


# --- Users ---


class UserBase(BaseModel):
    full_name: str = Field(min_length=2, max_length=150)
    email: InternalEmail
    phone: str | None = Field(None, max_length=20)
    role: UserRole
    employee_code: str | None = Field(None, max_length=40)
    is_active: bool = True


class UserCreate(UserBase):
    password: str

    @field_validator("password")
    @classmethod
    def check_password(cls, v: str) -> str:
        return _validate_password(v)


class UserUpdate(BaseModel):
    """All fields optional — PATCH semantics."""

    full_name: str | None = Field(None, min_length=2, max_length=150)
    email: InternalEmail | None = None
    phone: str | None = Field(None, max_length=20)
    role: UserRole | None = None
    employee_code: str | None = Field(None, max_length=40)
    is_active: bool | None = None


class UserPasswordReset(BaseModel):
    """Admin-initiated reset — no current password required."""

    new_password: str

    @field_validator("new_password")
    @classmethod
    def check_new(cls, v: str) -> str:
        return _validate_password(v)


class UserOut(BaseModel):
    model_config = ConfigDict(from_attributes=True)

    id: int
    full_name: str
    email: InternalEmail
    phone: str | None
    role: UserRole
    employee_code: str | None
    is_active: bool
    last_login_at: DhakaDateTime | None
    created_at: DhakaDateTime


class UserBrief(BaseModel):
    """Compact shape for dropdowns and nested references."""

    model_config = ConfigDict(from_attributes=True)

    id: int
    full_name: str
    role: UserRole
