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


class TransportType(str, Enum):
    BUS = "bus"
    FLIGHT = "flight"
    TRAIN = "train"
    CAR = "car"
    BOAT = "boat"
    OTHER = "other"


class HotelBase(BaseModel):
    service_provider_id: str
    name: str
    star_rating: Optional[int] = None
    address_line1: Optional[str] = None
    address_line2: Optional[str] = None
    city: Optional[str] = None
    state: Optional[str] = None
    country: Optional[str] = None
    postal_code: Optional[str] = None
    latitude: Optional[float] = None
    longitude: Optional[float] = None
    phone: Optional[str] = None
    email: Optional[EmailStr] = None
    website: Optional[str] = None
    check_in_time: Optional[time] = None
    check_out_time: Optional[time] = None
    description: Optional[str] = None
    policies: Optional[str] = None
    is_active: bool = True

    @field_validator("star_rating")
    @classmethod
    def validate_star_rating(cls, v):
        if v is not None and (v < 1 or v > 5):
            raise ValueError("Hotel star rating must be between 1 and 5")
        return v


class HotelCreate(HotelBase):
    pass


class HotelUpdate(BaseModel):
    service_provider_id: Optional[str] = None
    name: Optional[str] = None
    star_rating: Optional[int] = None
    address_line1: Optional[str] = None
    address_line2: Optional[str] = None
    city: Optional[str] = None
    state: Optional[str] = None
    country: Optional[str] = None
    postal_code: Optional[str] = None
    latitude: Optional[float] = None
    longitude: Optional[float] = None
    phone: Optional[str] = None
    email: Optional[EmailStr] = None
    website: Optional[str] = None
    check_in_time: Optional[time] = None
    check_out_time: Optional[time] = None
    description: Optional[str] = None
    policies: Optional[str] = None
    is_active: Optional[bool] = None

    @field_validator("star_rating")
    @classmethod
    def validate_star_rating(cls, v):
        if v is not None and (v < 1 or v > 5):
            raise ValueError("Hotel star rating must be between 1 and 5")
        return v


class HotelResponse(HotelBase):
    id: str
    created_at: datetime
    updated_at: datetime

    model_config = ConfigDict(from_attributes=True)


class HotelamenityBase(BaseModel):
    hotel_id: str
    amenity_id: str


class HotelamenityCreate(HotelamenityBase):
    pass


class HotelamenityUpdate(BaseModel):
    hotel_id: Optional[str] = None
    amenity_id: Optional[str] = None


class HotelamenityResponse(HotelamenityBase):
    id: str
    created_at: datetime
    updated_at: datetime

    model_config = ConfigDict(from_attributes=True)


class RoomtypeBase(BaseModel):
    hotel_id: str
    name: str
    description: Optional[str] = None
    max_occupancy: int
    bed_configuration: Optional[str] = None
    room_size_sqm: Optional[float] = None
    price_per_night: float
    total_rooms: int

    @field_validator("max_occupancy")
    @classmethod
    def validate_max_occupancy(cls, v):
        if v < 1:
            raise ValueError("Maximum occupancy must be at least 1")
        return v

    @field_validator("price_per_night")
    @classmethod
    def validate_price_per_night(cls, v):
        if v <= 0:
            raise ValueError("Price per night must be greater than zero")
        return v

    @field_validator("total_rooms")
    @classmethod
    def validate_total_rooms(cls, v):
        if v < 1:
            raise ValueError("Total rooms must be at least 1")
        return v


class RoomtypeCreate(RoomtypeBase):
    pass


class RoomtypeUpdate(BaseModel):
    hotel_id: Optional[str] = None
    name: Optional[str] = None
    description: Optional[str] = None
    max_occupancy: Optional[int] = None
    bed_configuration: Optional[str] = None
    room_size_sqm: Optional[float] = None
    price_per_night: Optional[float] = None
    total_rooms: Optional[int] = None

    @field_validator("max_occupancy")
    @classmethod
    def validate_max_occupancy(cls, v):
        if v is not None and v < 1:
            raise ValueError("Maximum occupancy must be at least 1")
        return v

    @field_validator("price_per_night")
    @classmethod
    def validate_price_per_night(cls, v):
        if v is not None and v <= 0:
            raise ValueError("Price per night must be greater than zero")
        return v

    @field_validator("total_rooms")
    @classmethod
    def validate_total_rooms(cls, v):
        if v is not None and v < 1:
            raise ValueError("Total rooms must be at least 1")
        return v


class RoomtypeResponse(RoomtypeBase):
    id: str
    created_at: datetime
    updated_at: datetime

    model_config = ConfigDict(from_attributes=True)


class TransportationBase(BaseModel):
    service_provider_id: str
    transport_type: TransportType
    vehicle_name: Optional[str] = None
    vehicle_number: Optional[str] = None
    capacity: int
    amenities: Optional[str] = None
    is_active: bool = True

    @field_validator("capacity")
    @classmethod
    def validate_capacity(cls, v):
        if v < 1:
            raise ValueError("Capacity must be at least 1")
        return v


class TransportationCreate(TransportationBase):
    pass


class TransportationUpdate(BaseModel):
    service_provider_id: Optional[str] = None
    transport_type: Optional[TransportType] = None
    vehicle_name: Optional[str] = None
    vehicle_number: Optional[str] = None
    capacity: Optional[int] = None
    amenities: Optional[str] = None
    is_active: Optional[bool] = None

    @field_validator("capacity")
    @classmethod
    def validate_capacity(cls, v):
        if v is not None and v < 1:
            raise ValueError("Capacity must be at least 1")
        return v


class TransportationResponse(TransportationBase):
    id: str
    created_at: datetime
    updated_at: datetime

    model_config = ConfigDict(from_attributes=True)


class AmenityResponse(BaseModel):
    id: str
    name: str
    description: Optional[str] = None
    icon_url: Optional[str] = None
    amenity_type: str

    model_config = ConfigDict(from_attributes=True)


class ServiceProviderResponse(BaseModel):
    id: str
    company_name: str
    service_type: str
    contact_email: Optional[str] = None

    model_config = ConfigDict(from_attributes=True)


class HotelDetailResponse(HotelResponse):
    service_provider: ServiceProviderResponse
    room_types: List[RoomtypeResponse]
    hotel_amenities: List["HotelAmenityDetailResponse"]

    model_config = ConfigDict(from_attributes=True)


class HotelAmenityDetailResponse(BaseModel):
    id: str
    amenity: AmenityResponse

    model_config = ConfigDict(from_attributes=True)