from pydantic import BaseModel, EmailStr, field_validator, model_validator
from typing import Optional
import re


class LoginRequest(BaseModel):
    identifier: str  # email, phone, username, or stem_id
    password: str

    @field_validator("password")
    @classmethod
    def password_not_empty(cls, v):
        if not v or len(v.strip()) == 0:
            raise ValueError("Password cannot be empty")
        return v


class RegisterStudentRequest(BaseModel):
    first_name: str
    last_name: str
    email: Optional[EmailStr] = None
    phone: Optional[str] = None
    password: str
    date_of_birth: Optional[str] = None
    gender: Optional[str] = None
    grade_id: Optional[int] = None

    @field_validator("password")
    @classmethod
    def validate_password(cls, v):
        if len(v) < 6:
            raise ValueError("Password must be at least 6 characters")
        return v

    @model_validator(mode="after")
    def email_or_phone_required(self):
        if not self.email and not self.phone:
            raise ValueError("Either email or phone number is required")
        return self


class RegisterParentRequest(BaseModel):
    first_name: str
    last_name: str
    email: EmailStr
    phone: Optional[str] = None
    password: str
    occupation: Optional[str] = None

    @field_validator("password")
    @classmethod
    def validate_password(cls, v):
        if len(v) < 6:
            raise ValueError("Password must be at least 6 characters")
        return v


class RegisterSchoolRequest(BaseModel):
    school_name: str
    email: EmailStr
    phone: Optional[str] = None
    password: str
    school_type: str = "primary"
    address: Optional[str] = None
    city: Optional[str] = None
    country: str = "Uganda"
    contact_email: Optional[EmailStr] = None
    contact_phone: Optional[str] = None
    registration_number: Optional[str] = None

    @field_validator("password")
    @classmethod
    def validate_password(cls, v):
        if len(v) < 6:
            raise ValueError("Password must be at least 6 characters")
        return v


class RegisterTeacherRequest(BaseModel):
    first_name: str
    last_name: str
    email: EmailStr
    phone: Optional[str] = None
    password: str
    specialization: Optional[str] = None
    qualifications: Optional[str] = None
    experience_years: int = 0

    @field_validator("password")
    @classmethod
    def validate_password(cls, v):
        if len(v) < 6:
            raise ValueError("Password must be at least 6 characters")
        return v


class RegisterOrganizationRequest(BaseModel):
    org_name: str
    email: EmailStr
    phone: Optional[str] = None
    password: str
    org_type: str = "private"
    address: Optional[str] = None
    city: Optional[str] = None
    country: str = "Uganda"
    registration_number: Optional[str] = None

    @field_validator("password")
    @classmethod
    def validate_password(cls, v):
        if len(v) < 6:
            raise ValueError("Password must be at least 6 characters")
        return v


class TokenResponse(BaseModel):
    access_token: str
    refresh_token: str
    token_type: str = "bearer"
    role: str
    stem_id: str
    user_id: int
    full_name: str


class RefreshTokenRequest(BaseModel):
    refresh_token: str


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

    @field_validator("new_password")
    @classmethod
    def validate_new_password(cls, v):
        if len(v) < 8:
            raise ValueError("Password must be at least 8 characters")
        if not re.search(r"[A-Z]", v):
            raise ValueError("Password must contain at least one uppercase letter")
        if not re.search(r"\d", v):
            raise ValueError("Password must contain at least one digit")
        return v


class ForgotPasswordRequest(BaseModel):
    email: EmailStr


class ResetPasswordRequest(BaseModel):
    token: str
    new_password: str

    @field_validator("new_password")
    @classmethod
    def validate_new_password(cls, v):
        if len(v) < 8:
            raise ValueError("Password must be at least 8 characters")
        return v
