from uuid import UUID
from typing import Optional
from datetime import date, datetime

from pydantic import BaseModel, Field, field_validator, ConfigDict


class ComputerBase(BaseModel):
    nome_host: Optional[str] = Field(
        None,
        max_length=150,
        description="Nome do host/computador na rede")
    nome_usuario: Optional[str] = Field(
        None, max_length=150, description="Nome do usuário logado no sistema")
    numero_serie: Optional[str] = Field(
        None, max_length=255, description="Número de série do equipamento")
    modelo: Optional[str] = Field(
        None,
        max_length=150,
        description="Modelo do equipamento")
    fabricante: Optional[str] = Field(
        None, max_length=150, description="Fabricante do equipamento")
    sistema_operacional: Optional[str] = Field(
        None, max_length=150, description="Sistema operacional instalado")
    ram_instalada: Optional[int] = Field(
        None, description="Quantidade de RAM instalada em MB")
    placa_video: Optional[str] = Field(
        None, max_length=150, description="Modelo da placa de vídeo")
    discos: Optional[str] = Field(
        None,
        max_length=255,
        description="Descrição dos discos rígidos/SSDs")
    dominio: Optional[str] = Field(
        None,
        max_length=150,
        description="Domínio de rede ao qual pertence")
    localizacao: Optional[str] = Field(
        None, max_length=150, description="Localização física do equipamento")
    data_primeiro_registro: Optional[date] = Field(
        None, description="Data do primeiro registro (YYYY-MM-DD)")
    empresa_id: str = Field(..., description="ID da empresa associada")
    usuario_id: Optional[int] = Field(
        None, description="ID do usuário associado")

    model_config = ConfigDict(
        from_attributes=True,
        validate_assignment=True,
    )

    @field_validator("data_primeiro_registro", mode="before")
    @classmethod
    def _coerce_date(cls, value):
        if value is None or isinstance(value, date):
            return value
        if isinstance(value, datetime):
            return value.date()
        if isinstance(value, str):
            v = value.strip()
            try:
                return datetime.fromisoformat(v).date()
            except Exception:
                try:
                    return date.fromisoformat(v)
                except Exception:
                    return value
        return value


class ComputerCreate(ComputerBase):
    pass


class ComputerUpdate(BaseModel):
    nome_host: Optional[str] = Field(None, max_length=150)
    nome_usuario: Optional[str] = Field(None, max_length=150)
    numero_serie: Optional[str] = Field(None, max_length=255)
    modelo: Optional[str] = Field(None, max_length=150)
    fabricante: Optional[str] = Field(None, max_length=150)
    sistema_operacional: Optional[str] = Field(None, max_length=150)
    ram_instalada: Optional[int] = Field(None)
    placa_video: Optional[str] = Field(None, max_length=150)
    discos: Optional[str] = Field(None, max_length=255)
    dominio: Optional[str] = Field(None, max_length=150)
    localizacao: Optional[str] = Field(None, max_length=150)
    data_primeiro_registro: Optional[date] = None
    empresa_id: Optional[str] = None
    usuario_id: Optional[int] = Field(
        None, description="ID do usuário associado")

    model_config = ConfigDict(
        from_attributes=True,
        validate_assignment=True,
    )

    @field_validator("data_primeiro_registro", mode="before")
    @classmethod
    def _coerce_date_update(cls, value):
        return ComputerBase._coerce_date(value)


class ComputerResponse(ComputerBase):
    id: UUID = Field(..., description="ID do computador")


class ComputerOnlineResponse(BaseModel):
    computador_id: UUID = Field(..., description="ID do computador")
    usuario: Optional[str] = Field(
        None,
        max_length=255,
        description="Nome do usuário logado",
    )
    ultimo_visto: Optional[datetime] = Field(
        None,
        description="Data e hora do último visto (YYYY-MM-DDTHH:MM:SS)",
    )
    online: int = Field(
        ...,
        description="Status online (1 para online, 0 para offline)",
    )

    model_config = ConfigDict(from_attributes=True)

    @field_validator("ultimo_visto", mode="before")
    @classmethod
    def _coerce_datetime(cls, value):
        if value is None or isinstance(value, datetime):
            return value
        if isinstance(value, str):
            v = value.strip()
            try:
                return datetime.fromisoformat(v)
            except Exception:
                return value
        return value


class ComputerOnlineCreate(BaseModel):
    computador_id: UUID = Field(..., description="ID do computador")
    usuario: Optional[str] = Field(
        None,
        max_length=255,
        description="Nome do usuário logado",
    )
    ultimo_visto: Optional[datetime] = Field(
        None,
        description="Data e hora do último visto (YYYY-MM-DDTHH:MM:SS)",
    )
    online: int = Field(
        ...,
        description="Status online (1 para online, 0 para offline)",
    )

    model_config = ConfigDict(from_attributes=True)

    @field_validator("ultimo_visto", mode="before")
    @classmethod
    def _coerce_datetime_create(cls, value):
        return ComputerOnlineResponse._coerce_datetime(value)


class ComputerOnlineUpdate(BaseModel):
    usuario: Optional[str] = Field(
        None,
        max_length=255,
        description="Nome do usuário logado")
    ultimo_visto: Optional[datetime] = Field(
        None, description="Data e hora do último visto (YYYY-MM-DDTHH:MM:SS)")
    online: Optional[int] = Field(
        None, description="Status online (1 para online, 0 para offline)")

    model_config = ConfigDict(from_attributes=True)

    @field_validator("ultimo_visto", mode="before")
    @classmethod
    def _coerce_datetime_update(cls, value):
        return ComputerOnlineResponse._coerce_datetime(value)
