from datetime import date
from typing import Literal, Optional

from fastapi import UploadFile
from pydantic import BaseModel, EmailStr, model_validator, ConfigDict

from core.config import get_db
from core.security.exceptions import CoreValidationError
from models import User, Parent, Participant, Staff


class UserBaseSchema(BaseModel):
    first_name: str
    last_name: str
    email: EmailStr
    mobile_number: str
    model_config = ConfigDict(from_attributes=True)


class UserCreateSchema(UserBaseSchema):
    password: str
    dob:Optional[date]=None
    confirm_password: str
    user_type: Literal['parent', 'participant', 'guest','staff']

    @model_validator(mode='after')
    def validate_fields(self):
        if self.password != self.confirm_password:
            raise CoreValidationError("given passwords are mismatch")
        if self.user_type=='participant' and self.dob is None:
            raise CoreValidationError("DOB is mandatory for participant registration")
        with get_db() as db:
            models={
                'parent':Parent,
                'admin':User,
                'participant':Participant,
                'guest':User,
                'staff':Staff
            }
            model=models[self.user_type]
            if db.query(model).where(model.email == self.email).count() > 0:
                raise CoreValidationError(f"Account already exists with {self.email}")
        return self


class UserLoginSchema(BaseModel):
    username: str
    password: str
    user_type:str


class ProfileBaseSchema(BaseModel):
    sur_name: str
    given_name: str
    dob: date
    age: int
    address: str
    post_code: int
    local_authority: str
    gender: str
    email: str
    emergency_contact_name: str
    second_emergency_contact: str
    medical_needs: str
    ethnicity: str
    care_experience: Optional[str] = None
    age_above_three: Optional[str] = None
    wac_receipt: Optional[str] = None


class ProfileSchema(ProfileBaseSchema):
    pass


class ProfileResponseSchema(ProfileBaseSchema):
    id: int
    profile_image: str | None
    profile_image_url: str | None
    wallet: float
    user: UserBaseSchema
    model_config = ConfigDict(from_attributes=True)


class ProfileImage(BaseModel):
    image: UploadFile
    user_id:int
    user_type:str

    @model_validator(mode='after')
    def validate_file_type(self):
        valid_type = ['image/jpg', 'image/png', 'image/jpeg']
        if self.image.content_type not in valid_type:
            raise CoreValidationError("Invalid image type")
        return self


class ProfileSchemaForParentList(ProfileBaseSchema):
    model_config = ConfigDict(from_attributes=True)


class ParentSchema(BaseModel):
    id: int
    first_name: str
    last_name: str
    email: EmailStr
    mobile_number: str
    user_profile: Optional[ProfileSchemaForParentList]
    no_of_participant: Optional[int] = None
    model_config = ConfigDict(from_attributes=True)



class GuestProfileSchema(BaseModel):
    first_name: str
    sur_name: str
    email: EmailStr
    address: Optional[str] = None
    post_code: Optional[str] = None
    mobile_number: Optional[str] = None
    alternative_contact_email: Optional[EmailStr] = None
    alternative_phone_number: Optional[str] = None
    wallet_amount: Optional[float] = 0.0
    term_and_condition_accepted: Optional[bool] = False

class GuestResponseSchema(GuestProfileSchema):
    id: int
    profile_image: str | None
    profile_image_url: str | None
    model_config = ConfigDict(from_attributes=True)

class StaffProfileUpdateSchema(BaseModel):
    first_name: str
    last_name: str
    email: str
    mobile_number: str
    dbs_status: bool

class ForgotPasswordRequest(BaseModel):
    email: EmailStr
    user_type: str

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


class ChangePasswordRequest(BaseModel):
    old_password: str
    new_password: str
    user_type: str
