from sqlalchemy import Column, Integer, String, DateTime, Numeric, Boolean, Text, Enum, JSON
from sqlalchemy.orm import relationship
from datetime import datetime
import enum
from ...shared.config.database import Base

class DiscountType(str, enum.Enum):
    percentage = 'percentage'
    fixed_amount = 'fixed_amount'

class Promotion(Base):
    __tablename__ = 'promotions'
    id = Column(Integer, primary_key=True, index=True, autoincrement=True)
    code = Column(String(50), unique=True, nullable=False, index=True)
    name = Column(String(100), nullable=False)
    description = Column(Text, nullable=True)
    discount_type = Column(Enum(DiscountType), nullable=False)
    discount_value = Column(Numeric(10, 2), nullable=False)
    min_booking_amount = Column(Numeric(10, 2), nullable=True)
    max_discount_amount = Column(Numeric(10, 2), nullable=True)
    min_stay_days = Column(Integer, nullable=True, comment="Minimum number of nights required for booking")
    max_stay_days = Column(Integer, nullable=True, comment="Maximum number of nights allowed for booking")
    advance_booking_days = Column(Integer, nullable=True, comment="Minimum days in advance the booking must be made")
    max_advance_booking_days = Column(Integer, nullable=True, comment="Maximum days in advance the booking can be made")
    
    # Day of week restrictions (0=Monday, 6=Sunday, stored as JSON array like [0,1,2] for Mon-Wed)
    allowed_check_in_days = Column(JSON, nullable=True, comment="Allowed check-in days of week (0-6, Mon-Sun)")
    allowed_check_out_days = Column(JSON, nullable=True, comment="Allowed check-out days of week (0-6, Mon-Sun)")
    
    # Room type restrictions (stored as JSON array of room type IDs or names)
    allowed_room_type_ids = Column(JSON, nullable=True, comment="Allowed room type IDs (JSON array)")
    excluded_room_type_ids = Column(JSON, nullable=True, comment="Excluded room type IDs (JSON array)")
    
    # Guest count restrictions
    min_guests = Column(Integer, nullable=True, comment="Minimum number of guests required")
    max_guests = Column(Integer, nullable=True, comment="Maximum number of guests allowed")
    
    # Customer type restrictions
    first_time_customer_only = Column(Boolean, nullable=False, default=False, comment="Only for first-time customers")
    repeat_customer_only = Column(Boolean, nullable=False, default=False, comment="Only for returning customers")
    
    # Blackout dates (stored as JSON array of date strings)
    blackout_dates = Column(JSON, nullable=True, comment="Blackout dates when promotion doesn't apply (JSON array of YYYY-MM-DD)")
    
    start_date = Column(DateTime, nullable=False)
    end_date = Column(DateTime, nullable=False)
    usage_limit = Column(Integer, nullable=True)
    used_count = Column(Integer, nullable=False, default=0)
    is_active = Column(Boolean, nullable=False, default=True)
    created_at = Column(DateTime, default=datetime.utcnow, nullable=False)
    updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False)

    def is_valid(self):
        from datetime import datetime
        now = datetime.utcnow()
        if not self.is_active:
            return False
        if now < self.start_date or now > self.end_date:
            return False
        if self.usage_limit is not None and self.used_count >= self.usage_limit:
            return False
        return True

    def calculate_discount(self, booking_amount):
        if not self.is_valid():
            return 0.0
        if self.min_booking_amount and booking_amount < float(self.min_booking_amount):
            return 0.0
        discount = 0.0
        if self.discount_type == DiscountType.percentage:
            discount = float(booking_amount) * float(self.discount_value) / 100.0
        elif self.discount_type == DiscountType.fixed_amount:
            discount = float(self.discount_value)
        if self.max_discount_amount and discount > float(self.max_discount_amount):
            discount = float(self.max_discount_amount)
        return discount