"""User model for application users."""
from typing import Annotated, List, Optional

from pydantic import (
    Secret, Field, EmailStr, StringConstraints, field_validator,
    model_validator, field_serializer
)

from .test import PyObjectId
from .base import BaseDocument

ROLES = {"practitioner", "patient", "admin"}

class User(BaseDocument):
    """User model representing application users."""
    # Basic information
    username: Annotated[
        str,
        StringConstraints(min_length=4, max_length=50, strip_whitespace=True)
    ] = Field(description="Username of the user")
    dispName: Annotated[
        str,
        StringConstraints(min_length=1, strip_whitespace=True)
    ] = Field(description="Display name of the user")
    email: EmailStr = Field(description="Email address of the user")
    passwdHash: Secret[str] = Field(description="Hashed password of the user")

    # Security and roles
    roles: List[str] = Field(default=['patient'], description="List of roles assigned to the user")
    active: bool = Field(default=True, description="Indicates if the user is active")

    # Demographic information
    residentCountry: Annotated[
        str,
        StringConstraints(min_length=1, max_length=4, strip_whitespace=True)
    ] = Field(default="TR", description="Country code of the user (ISO 3166-1 alpha-2)")

    residentCity: Annotated[
        str,
        StringConstraints(min_length=1, strip_whitespace=True)
    ] = Field(default="Ankara", description="City of the user")

    # Medical information
    bloodType: Optional[str] = Field(
        default=None, description="Blood type of the user"
    )
    height: Optional[float] = Field(
        default=None, gt=0, description="Height of the user in cm"
    )
    weight: Optional[float] = Field(
        default=None, gt=0, description="Weight of the user in kg"
    )

    allergies: List[str] = Field(
        default_factory=list, description="List of allergies the user has"
    )

    sharingInfo: List[PyObjectId] = Field(
        default_factory=list,
        description="List of user IDs sharing the user's information"
    )

    deviceConnections: List[str] = Field(
        default_factory=list,
        description="List of device connection IDs (references to device_connections collection)"
    )

    # Practitioner-specific fields (only relevant when 'practitioner' in roles)
    specialty: Optional[str] = Field(
        default=None, description="Medical specialty (e.g., 'Kardiyoloji', 'Dermatoloji')"
    )
    hospital: Optional[str] = Field(
        default=None, description="Primary hospital affiliation"
    )
    department: Optional[str] = Field(
        default=None, description="Department within the hospital"
    )
    title: Optional[str] = Field(
        default=None, description="Professional title (e.g., 'Uzman', 'Profesör', 'Doçent')"
    )
    phoneNumber: Optional[str] = Field(
        default=None, description="Contact phone number"
    )

    @field_validator("roles")
    @classmethod
    def validate_roles(cls, v: List[str]) -> List[str]:
        """Validate that roles are from the allowed set."""
        if not set(v).issubset(ROLES):
            raise ValueError(f"roles must be a subset of {ROLES}")
        return v

    @field_serializer("passwdHash")
    def _serialize_password_hash(self, v: Secret[str] | None):
        """Serialize password hash by extracting the secret value."""
        return v.get_secret_value() if v is not None else None

    @model_validator(mode="after")
    def check_active_consistency(self):
        """Ensure inactive users don't have roles."""
        if not self.active and self.roles:
            raise ValueError("Inactive users cannot have roles assigned.")
        return self
