"""
Reservation schemas for booking management.
"""
from typing import Optional, List
from datetime import datetime, date
from pydantic import BaseModel, Field, field_validator

from app.models.reservation import ReservationStatus, ReservationSource


class ReservationBase(BaseModel):
    """Base reservation schema."""
    client_id: int
    room_id: int
    check_in_date: date
    check_out_date: date
    adults: int = Field(1, ge=1)
    children: int = Field(0, ge=0)
    rate_per_night: float = Field(..., ge=0)
    source: ReservationSource = ReservationSource.DIRECT
    special_requests: Optional[str] = None
    internal_notes: Optional[str] = None

    @field_validator('check_out_date')
    @classmethod
    def check_out_after_check_in(cls, v, info):
        if 'check_in_date' in info.data and v <= info.data['check_in_date']:
            raise ValueError('Check-out date must be after check-in date')
        return v


class ReservationCreate(ReservationBase):
    """Schema for creating a reservation."""
    deposit_amount: float = Field(0.0, ge=0)
    currency: str = Field("XOF", max_length=3)
    group_id: Optional[str] = None


class ReservationUpdate(BaseModel):
    """Schema for updating a reservation."""
    room_id: Optional[int] = None
    check_in_date: Optional[date] = None
    check_out_date: Optional[date] = None
    adults: Optional[int] = Field(None, ge=1)
    children: Optional[int] = Field(None, ge=0)
    rate_per_night: Optional[float] = Field(None, ge=0)
    source: Optional[ReservationSource] = None
    special_requests: Optional[str] = None
    internal_notes: Optional[str] = None
    deposit_amount: Optional[float] = Field(None, ge=0)


class ReservationStatusUpdate(BaseModel):
    """Schema for updating reservation status."""
    status: ReservationStatus
    reason: Optional[str] = None


class ReservationResponse(BaseModel):
    """Schema for reservation response."""
    id: int
    client_id: int
    room_id: int
    check_in_date: date
    check_out_date: date
    actual_check_in: Optional[datetime] = None
    actual_check_out: Optional[datetime] = None
    status: ReservationStatus
    source: ReservationSource
    adults: int
    children: int
    rate_per_night: float
    total_price: float
    deposit_amount: float
    currency: str
    special_requests: Optional[str] = None
    internal_notes: Optional[str] = None
    confirmation_number: str
    group_id: Optional[str] = None
    nights: int
    total_guests: int
    is_active: bool
    created_at: datetime
    updated_at: datetime

    # Nested objects (optional loading)
    client: Optional[dict] = None
    room: Optional[dict] = None
    folio: Optional[dict] = None

    class Config:
        from_attributes = True


class ReservationCalendarItem(BaseModel):
    """Schema for calendar view item."""
    id: int
    title: str
    start: date
    end: date
    room_id: int
    room_number: str
    client_name: str
    status: ReservationStatus
    color: Optional[str] = None


class ReservationFilter(BaseModel):
    """Schema for filtering reservations."""
    start_date: Optional[date] = None
    end_date: Optional[date] = None
    status: Optional[List[ReservationStatus]] = None
    room_id: Optional[int] = None
    client_id: Optional[int] = None
    source: Optional[ReservationSource] = None
    confirmation_number: Optional[str] = None
    limit: int = Field(50, ge=1, le=500)
    offset: int = Field(0, ge=0)


class CheckInRequest(BaseModel):
    """Schema for check-in request."""
    reservation_id: int
    room_id: Optional[int] = None
    notes: Optional[str] = None


class CheckOutRequest(BaseModel):
    """Schema for check-out request."""
    reservation_id: int
    notes: Optional[str] = None
    force: bool = False


class ArrivalsDepatures(BaseModel):
    """Schema for arrivals/departures response."""
    date: date
    arrivals: List[ReservationResponse]
    departures: List[ReservationResponse]
    in_house: List[ReservationResponse]


class ReservationListResponse(BaseModel):
    """Paginated reservation list response."""
    items: List[ReservationResponse]
    total: int
    page: int
    page_size: int
    total_pages: int
