from pydantic import BaseModel, EmailStr, Field, field_validator, ConfigDict
from typing import Optional, List
from datetime import datetime, date
from enum import Enum


class UserRole(str, Enum):
    SUPER_ADMIN = "super_admin"
    TOUR_MANAGER = "tour_manager"
    BOOKING_AGENT = "booking_agent"
    TOUR_GUIDE = "tour_guide"
    SERVICE_PROVIDER = "service_provider"
    CUSTOMER = "customer"
    FINANCE_MANAGER = "finance_manager"


class LoyaltyStatus(str, Enum):
    BRONZE = "bronze"
    SILVER = "silver"
    GOLD = "gold"
    PLATINUM = "platinum"


class ServiceType(str, Enum):
    HOTEL = "hotel"
    TRANSPORTATION = "transportation"
    RESTAURANT = "restaurant"
    ACTIVITY = "activity"
    INSURANCE = "insurance"
    OTHER = "other"


# User schemas
class UserBase(BaseModel):
    email: EmailStr
    role: UserRole
    first_name: str = Field(..., min_length=1, max_length=100)
    last_name: str = Field(..., min_length=1, max_length=100)
    phone: Optional[str] = Field(None, max_length=50)
    is_active: bool = True

    @field_validator("email")
    @classmethod
    def validate_email_format(cls, v: str) -> str:
        if not v or "@" not in v:
            raise ValueError("Email must be valid format")
        return v


class UserCreate(UserBase):
    password: str = Field(..., min_length=8)

    @field_validator("password")
    @classmethod
    def validate_password_strength(cls, v: str) -> str:
        if len(v) < 8:
            raise ValueError("Password minimum 8 characters")
        if not any(c.isupper() for c in v):
            raise ValueError("Password must contain uppercase letter")
        if not any(c.islower() for c in v):
            raise ValueError("Password must contain lowercase letter")
        if not any(c.isdigit() for c in v):
            raise ValueError("Password must contain number")
        if not any(c in "!@#$%^&*()_+-=[]{}|;:,.<>?" for c in v):
            raise ValueError("Password must contain special character")
        return v


class UserUpdate(BaseModel):
    email: Optional[EmailStr] = None
    role: Optional[UserRole] = None
    first_name: Optional[str] = Field(None, min_length=1, max_length=100)
    last_name: Optional[str] = Field(None, min_length=1, max_length=100)
    phone: Optional[str] = Field(None, max_length=50)
    is_active: Optional[bool] = None
    password: Optional[str] = Field(None, min_length=8)

    @field_validator("password")
    @classmethod
    def validate_password_strength(cls, v: Optional[str]) -> Optional[str]:
        if v is None:
            return v
        if len(v) < 8:
            raise ValueError("Password minimum 8 characters")
        if not any(c.isupper() for c in v):
            raise ValueError("Password must contain uppercase letter")
        if not any(c.islower() for c in v):
            raise ValueError("Password must contain lowercase letter")
        if not any(c.isdigit() for c in v):
            raise ValueError("Password must contain number")
        if not any(c in "!@#$%^&*()_+-=[]{}|;:,.<>?" for c in v):
            raise ValueError("Password must contain special character")
        return v


class UserResponse(BaseModel):
    id: str
    email: str
    role: str
    first_name: str
    last_name: str
    phone: Optional[str]
    is_active: bool
    last_login_at: Optional[datetime]
    created_at: datetime
    updated_at: datetime

    model_config = ConfigDict(from_attributes=True)


# Customer schemas
class CustomerBase(BaseModel):
    date_of_birth: Optional[date] = None
    nationality: Optional[str] = Field(None, max_length=100)
    passport_number: Optional[str] = Field(None, max_length=50)
    passport_expiry: Optional[date] = None
    emergency_contact_name: Optional[str] = Field(None, max_length=100)
    emergency_contact_phone: Optional[str] = Field(None, max_length=50)
    address_line1: Optional[str] = Field(None, max_length=255)
    address_line2: Optional[str] = Field(None, max_length=255)
    city: Optional[str] = Field(None, max_length=100)
    state: Optional[str] = Field(None, max_length=100)
    country: Optional[str] = Field(None, max_length=100)
    postal_code: Optional[str] = Field(None, max_length=20)
    loyalty_status: Optional[LoyaltyStatus] = None
    loyalty_points: int = 0
    preferences: Optional[str] = None


class CustomerCreate(CustomerBase):
    user_id: str


class CustomerUpdate(BaseModel):
    date_of_birth: Optional[date] = None
    nationality: Optional[str] = Field(None, max_length=100)
    passport_number: Optional[str] = Field(None, max_length=50)
    passport_expiry: Optional[date] = None
    emergency_contact_name: Optional[str] = Field(None, max_length=100)
    emergency_contact_phone: Optional[str] = Field(None, max_length=50)
    address_line1: Optional[str] = Field(None, max_length=255)
    address_line2: Optional[str] = Field(None, max_length=255)
    city: Optional[str] = Field(None, max_length=100)
    state: Optional[str] = Field(None, max_length=100)
    country: Optional[str] = Field(None, max_length=100)
    postal_code: Optional[str] = Field(None, max_length=20)
    loyalty_status: Optional[LoyaltyStatus] = None
    loyalty_points: Optional[int] = None
    preferences: Optional[str] = None


class CustomerResponse(BaseModel):
    id: str
    user_id: str
    date_of_birth: Optional[date]
    nationality: Optional[str]
    passport_number: Optional[str]
    passport_expiry: Optional[date]
    emergency_contact_name: Optional[str]
    emergency_contact_phone: Optional[str]
    address_line1: Optional[str]
    address_line2: Optional[str]
    city: Optional[str]
    state: Optional[str]
    country: Optional[str]
    postal_code: Optional[str]
    loyalty_status: Optional[str]
    loyalty_points: int
    preferences: Optional[str]
    created_at: datetime
    updated_at: datetime

    model_config = ConfigDict(from_attributes=True)


# Tourguide schemas
class TourguideBase(BaseModel):
    languages_spoken: List[str]
    specializations: Optional[List[str]] = None
    certifications: Optional[str] = None
    license_number: Optional[str] = Field(None, max_length=50)
    license_expiry: Optional[date] = None
    years_of_experience: Optional[int] = None
    bio: Optional[str] = None
    rating: Optional[float] = None
    total_tours_conducted: int = 0
    is_available: bool = True


class TourguideCreate(TourguideBase):
    user_id: str


class TourguideUpdate(BaseModel):
    languages_spoken: Optional[List[str]] = None
    specializations: Optional[List[str]] = None
    certifications: Optional[str] = None
    license_number: Optional[str] = Field(None, max_length=50)
    license_expiry: Optional[date] = None
    years_of_experience: Optional[int] = None
    bio: Optional[str] = None
    rating: Optional[float] = None
    total_tours_conducted: Optional[int] = None
    is_available: Optional[bool] = None


class TourguideResponse(BaseModel):
    id: str
    user_id: str
    languages_spoken: List[str]
    specializations: Optional[List[str]]
    certifications: Optional[str]
    license_number: Optional[str]
    license_expiry: Optional[date]
    years_of_experience: Optional[int]
    bio: Optional[str]
    rating: Optional[float]
    total_tours_conducted: int
    is_available: bool
    created_at: datetime
    updated_at: datetime

    model_config = ConfigDict(from_attributes=True)


# Serviceprovider schemas
class ServiceproviderBase(BaseModel):
    company_name: str = Field(..., min_length=1, max_length=255)
    service_type: ServiceType
    registration_number: Optional[str] = Field(None, max_length=100)
    tax_id: Optional[str] = Field(None, max_length=100)
    contact_person: Optional[str] = Field(None, max_length=100)
    contact_email: Optional[EmailStr] = None
    contact_phone: Optional[str] = Field(None, max_length=50)
    address_line1: Optional[str] = Field(None, max_length=255)
    address_line2: Optional[str] = Field(None, max_length=255)
    city: Optional[str] = Field(None, max_length=100)
    state: Optional[str] = Field(None, max_length=100)
    country: Optional[str] = Field(None, max_length=100)
    postal_code: Optional[str] = Field(None, max_length=20)
    contract_start_date: Optional[date] = None
    contract_end_date: Optional[date] = None
    payment_terms: Optional[str] = None
    rating: Optional[float] = None
    is_verified: bool = False


class ServiceproviderCreate(ServiceproviderBase):
    user_id: str


class ServiceproviderUpdate(BaseModel):
    company_name: Optional[str] = Field(None, min_length=1, max_length=255)
    service_type: Optional[ServiceType] = None
    registration_number: Optional[str] = Field(None, max_length=100)
    tax_id: Optional[str] = Field(None, max_length=100)
    contact_person: Optional[str] = Field(None, max_length=100)
    contact_email: Optional[EmailStr] = None
    contact_phone: Optional[str] = Field(None, max_length=50)
    address_line1: Optional[str] = Field(None, max_length=255)
    address_line2: Optional[str] = Field(None, max_length=255)
    city: Optional[str] = Field(None, max_length=100)
    state: Optional[str] = Field(None, max_length=100)
    country: Optional[str] = Field(None, max_length=100)
    postal_code: Optional[str] = Field(None, max_length=20)
    contract_start_date: Optional[date] = None
    contract_end_date: Optional[date] = None
    payment_terms: Optional[str] = None
    rating: Optional[float] = None
    is_verified: Optional[bool] = None


class ServiceproviderResponse(BaseModel):
    id: str
    user_id: str
    company_name: str
    service_type: str
    registration_number: Optional[str]
    tax_id: Optional[str]
    contact_person: Optional[str]
    contact_email: Optional[str]
    contact_phone: Optional[str]
    address_line1: Optional[str]
    address_line2: Optional[str]
    city: Optional[str]
    state: Optional[str]
    country: Optional[str]
    postal_code: Optional[str]
    contract_start_date: Optional[date]
    contract_end_date: Optional[date]
    payment_terms: Optional[str]
    rating: Optional[float]
    is_verified: bool
    created_at: datetime
    updated_at: datetime

    model_config = ConfigDict(from_attributes=True)