from typing import Optional
from sqlmodel import SQLModel, Field
from datetime import datetime
from enum import Enum
from pydantic import field_validator

class Role(str, Enum):
    SUPERADMIN = "SUPERADMIN"
    ADMIN = "ADMIN"
    USERS = "USERS"

class User(SQLModel, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)
    first_name: Optional[str] = Field(default=None, max_length=100)
    last_name: Optional[str] = Field(default=None, max_length=100)
    email: str = Field(unique=True, index=True, nullable=False)
    hashed_password: str = Field(nullable=False)
    phone: Optional[str] = None
    role: Role = Field(default=Role.USERS)
    is_active: bool = Field(default=True)
    is_deleted: bool = Field(default=False)
    refresh_token: Optional[str] = None
    profile_image: Optional[str] = None
    created_at: datetime = Field(default_factory=datetime.utcnow)
    updated_at: datetime = Field(default_factory=datetime.utcnow, sa_column_kwargs={"onupdate": datetime.utcnow})

    # EMAIL NORMALIZER
    @field_validator("email", mode="before")
    @classmethod
    def normalize_email(cls, value: str) -> str:
        if value is None:
            return value
        return value.strip().lower()

    # FIRST NAME NORMALIZER
    @field_validator("first_name", mode="before")
    @classmethod
    def normalize_first_name(cls, v: Optional[str]) -> Optional[str]:
        if not v:
            return v
        # Remove extra spaces and capitalize properly
        return v.strip().capitalize()

    # LAST NAME NORMALIZER
    @field_validator("last_name", mode="before")
    @classmethod
    def normalize_last_name(cls, v: Optional[str]) -> Optional[str]:
        if not v:
            return v
        return v.strip().capitalize()

    # PHONE NORMALIZER
    @field_validator("phone", mode="before")
    @classmethod
    def normalize_phone(cls, v: Optional[str]) -> Optional[str]:
        if not v:
            return v
        # Remove spaces, hyphens, parentheses etc.
        digits = "".join(filter(str.isdigit, v))
        return digits if digits else None
