"""
Pydantic schemas for promotion-related requests and responses.
"""
from pydantic import BaseModel, Field, field_validator
from typing import Optional, List
from datetime import datetime


class ValidatePromotionRequest(BaseModel):
    """Schema for validating a promotion code."""
    code: str = Field(..., min_length=1, max_length=50, description="Promotion code")
    booking_value: Optional[float] = Field(None, ge=0, description="Booking value/amount")
    booking_amount: Optional[float] = Field(None, ge=0, description="Booking amount (alias for booking_value)")
    check_in_date: Optional[str] = Field(None, description="Check-in date (ISO format YYYY-MM-DD)")
    check_out_date: Optional[str] = Field(None, description="Check-out date (ISO format YYYY-MM-DD)")
    room_type_id: Optional[int] = Field(None, description="Room type ID for the booking")
    guest_count: Optional[int] = Field(None, ge=1, description="Number of guests")
    is_first_time_customer: Optional[bool] = Field(None, description="Whether customer is booking for the first time")
    
    @field_validator('code')
    @classmethod
    def validate_code(cls, v: str) -> str:
        """Validate promotion code format."""
        if not v or not v.strip():
            raise ValueError("Promotion code cannot be empty")
        return v.strip().upper()
    
    model_config = {
        "json_schema_extra": {
            "example": {
                "code": "SUMMER2024",
                "booking_value": 500.00,
                "check_in_date": "2024-06-15",
                "check_out_date": "2024-06-22"
            }
        }
    }


class CreatePromotionRequest(BaseModel):
    """Schema for creating a promotion."""
    code: str = Field(..., min_length=1, max_length=50, description="Promotion code")
    name: str = Field(..., min_length=1, max_length=200, description="Promotion name")
    description: Optional[str] = Field(None, max_length=1000)
    discount_type: str = Field(..., description="Discount type: 'percentage' or 'fixed'")
    discount_value: float = Field(..., gt=0, description="Discount value")
    min_booking_amount: Optional[float] = Field(None, ge=0)
    max_discount_amount: Optional[float] = Field(None, ge=0)
    min_stay_days: Optional[int] = Field(None, ge=1, description="Minimum number of nights required for booking")
    max_stay_days: Optional[int] = Field(None, ge=1, description="Maximum number of nights allowed for booking")
    advance_booking_days: Optional[int] = Field(None, ge=0, description="Minimum days in advance the booking must be made")
    max_advance_booking_days: Optional[int] = Field(None, ge=0, description="Maximum days in advance the booking can be made")
    
    # Day of week restrictions (0=Monday, 6=Sunday)
    allowed_check_in_days: Optional[List[int]] = Field(None, description="Allowed check-in days of week (0-6, Mon-Sun)")
    allowed_check_out_days: Optional[List[int]] = Field(None, description="Allowed check-out days of week (0-6, Mon-Sun)")
    
    # Room type restrictions
    allowed_room_type_ids: Optional[List[int]] = Field(None, description="Allowed room type IDs")
    excluded_room_type_ids: Optional[List[int]] = Field(None, description="Excluded room type IDs")
    
    # Guest count restrictions
    min_guests: Optional[int] = Field(None, ge=1, description="Minimum number of guests required")
    max_guests: Optional[int] = Field(None, ge=1, description="Maximum number of guests allowed")
    
    # Customer type restrictions
    first_time_customer_only: Optional[bool] = Field(False, description="Only for first-time customers")
    repeat_customer_only: Optional[bool] = Field(False, description="Only for returning customers")
    
    # Blackout dates (array of date strings YYYY-MM-DD)
    blackout_dates: Optional[List[str]] = Field(None, description="Blackout dates when promotion doesn't apply")
    
    start_date: Optional[str] = Field(None, description="Start date (ISO format)")
    end_date: Optional[str] = Field(None, description="End date (ISO format)")
    usage_limit: Optional[int] = Field(None, ge=1)
    status: Optional[str] = Field("active", description="Status: 'active' or 'inactive'")
    
    @field_validator('discount_type')
    @classmethod
    def validate_discount_type(cls, v: str) -> str:
        """Validate discount type."""
        if v not in ['percentage', 'fixed']:
            raise ValueError("Discount type must be 'percentage' or 'fixed'")
        return v
    
    @field_validator('discount_value')
    @classmethod
    def validate_discount_value(cls, v: float, info) -> float:
        """Validate discount value based on type."""
        if 'discount_type' in info.data and info.data['discount_type'] == 'percentage':
            if v > 100:
                raise ValueError("Percentage discount cannot exceed 100%")
        return v
    
    @field_validator('code')
    @classmethod
    def validate_code(cls, v: str) -> str:
        """Validate promotion code format."""
        if not v or not v.strip():
            raise ValueError("Promotion code cannot be empty")
        return v.strip().upper()
    
    model_config = {
        "json_schema_extra": {
            "example": {
                "code": "SUMMER2024",
                "name": "Summer Sale",
                "description": "20% off all bookings",
                "discount_type": "percentage",
                "discount_value": 20.0,
                "min_booking_amount": 100.0,
                "max_discount_amount": 500.0,
                "start_date": "2024-06-01T00:00:00Z",
                "end_date": "2024-08-31T23:59:59Z",
                "usage_limit": 100,
                "status": "active"
            }
        }
    }


class UpdatePromotionRequest(BaseModel):
    """Schema for updating a promotion."""
    code: Optional[str] = Field(None, min_length=1, max_length=50)
    name: Optional[str] = Field(None, min_length=1, max_length=200)
    description: Optional[str] = Field(None, max_length=1000)
    discount_type: Optional[str] = None
    discount_value: Optional[float] = Field(None, gt=0)
    min_booking_amount: Optional[float] = Field(None, ge=0)
    max_discount_amount: Optional[float] = Field(None, ge=0)
    min_stay_days: Optional[int] = Field(None, ge=1)
    max_stay_days: Optional[int] = Field(None, ge=1)
    advance_booking_days: Optional[int] = Field(None, ge=0)
    max_advance_booking_days: Optional[int] = Field(None, ge=0)
    
    allowed_check_in_days: Optional[List[int]] = None
    allowed_check_out_days: Optional[List[int]] = None
    
    allowed_room_type_ids: Optional[List[int]] = None
    excluded_room_type_ids: Optional[List[int]] = None
    
    min_guests: Optional[int] = Field(None, ge=1)
    max_guests: Optional[int] = Field(None, ge=1)
    
    first_time_customer_only: Optional[bool] = None
    repeat_customer_only: Optional[bool] = None
    
    blackout_dates: Optional[List[str]] = None
    
    start_date: Optional[str] = None
    end_date: Optional[str] = None
    usage_limit: Optional[int] = Field(None, ge=1)
    status: Optional[str] = None
    
    @field_validator('discount_type')
    @classmethod
    def validate_discount_type(cls, v: Optional[str]) -> Optional[str]:
        """Validate discount type if provided."""
        if v and v not in ['percentage', 'fixed']:
            raise ValueError("Discount type must be 'percentage' or 'fixed'")
        return v
    
    model_config = {
        "json_schema_extra": {
            "example": {
                "name": "Updated Summer Sale",
                "discount_value": 25.0,
                "status": "active"
            }
        }
    }

