from __future__ import annotations

from typing import List, Optional

from pydantic import BaseModel, ConfigDict, Field, field_validator


def _cpf_validator(value: str | None) -> str | None:
    if value is None:
        return None
    digits = ''.join(filter(str.isdigit, value))
    if not digits:
        raise ValueError('CPF inválido.')
    if len(digits) != 11 or digits == digits[0] * 11:
        raise ValueError('CPF inválido.')

    def _calc_digit(seq: str, multiplier: int) -> int:
        total = sum(int(num) * (multiplier - idx) for idx, num in enumerate(seq))
        remainder = (total * 10) % 11
        return 0 if remainder == 10 else remainder

    first = _calc_digit(digits[:9], 10)
    second = _calc_digit(digits[:10], 11)
    if first != int(digits[9]) or second != int(digits[10]):
        raise ValueError('CPF inválido.')
    return digits


class UsuarioDataBase(BaseModel):
    nome_completo: str = Field(
        alias="nome-completo",
        serialization_alias="nome-completo",
        min_length=1,
        max_length=255,
        description="Nome completo do usuário",
        examples=["Ana Carolina Costa"],
    )
    nome_social: str | None = Field(
        default=None,
        alias="nome-social",
        serialization_alias="nome-social",
        min_length=1,
        max_length=255,
        description="Nome social, se aplicável",
        examples=["Carol Costa"],
    )
    cpf: str | None = Field(
        default=None,
        max_length=20,
        description="CPF válido do usuário",
        examples=["12345678901"],
    )
    enderecos: List[str] = Field(
        alias="enderecos",
        serialization_alias="enderecos",
        description="Lista de identificadores de endereços",
        default_factory=list,
        examples=[["endereco_01", "endereco_02"]],
    )
    email: str | None = Field(
        default=None,
        max_length=255,
        description="E-mail de contato",
        examples=["ana.costa@empresa.com"],
    )

    @field_validator("cpf")
    @classmethod
    def _validate_cpf(cls, value: str | None) -> str | None:
        return _cpf_validator(value)


class UsuarioDataCreate(UsuarioDataBase):
    """Payload de criação para dados de usuário."""


class UsuarioDataUpdate(BaseModel):
    nome_completo: str | None = Field(
        default=None,
        alias="nome-completo",
        serialization_alias="nome-completo",
        min_length=1,
        max_length=255,
        description="Nome completo do usuário",
    )
    nome_social: str | None = Field(
        default=None,
        alias="nome-social",
        serialization_alias="nome-social",
        min_length=1,
        max_length=255,
        description="Nome social, se aplicável",
    )
    cpf: str | None = Field(
        default=None,
        max_length=20,
        description="CPF válido do usuário",
    )
    enderecos: List[str] | None = Field(
        default=None,
        alias="enderecos",
        serialization_alias="enderecos",
        description="Lista de identificadores de endereços",
    )
    email: str | None = Field(
        default=None,
        max_length=255,
        description="E-mail de contato",
    )

    @field_validator("cpf")
    @classmethod
    def _validate_cpf(cls, value: str | None) -> str | None:
        return _cpf_validator(value)


class UsuarioDataOut(BaseModel):
    id: str
    nome_completo: str = Field(serialization_alias="nome-completo")
    nome_social: Optional[str] = Field(serialization_alias="nome-social", default=None)
    cpf: Optional[str]
    enderecos: List[str]
    email: Optional[str]
    createdAt: str
    updatedAt: str

    model_config = ConfigDict(
        from_attributes=True,
        populate_by_name=True,
        json_schema_extra={
            "example": {
                "id": "usuario_data_01",
                "nome-completo": "Ana Carolina Costa",
                "nome-social": "Carol Costa",
                "cpf": "12345678901",
                "enderecos": ["endereco_01"],
                "email": "ana.costa@empresa.com",
                "createdAt": "2025-01-05T10:00:00.000Z",
                "updatedAt": "2025-01-05T10:00:00.000Z",
            }
        },
    )


class PaginatedUsuariosData(BaseModel):
    items: List[UsuarioDataOut]
    total: int

    model_config = ConfigDict(
        json_schema_extra={
            "example": {
                "items": [
                    {
                        "id": "usuario_data_01",
                        "nome-completo": "Ana Carolina Costa",
                        "nome-social": "Carol Costa",
                        "cpf": "12345678901",
                        "enderecos": ["endereco_01"],
                        "email": "ana.costa@empresa.com",
                        "createdAt": "2025-01-05T10:00:00.000Z",
                        "updatedAt": "2025-01-05T10:00:00.000Z",
                    }
                ],
                "total": 1,
            }
        }
    )
