import uuid
from datetime import datetime
from sqlalchemy import Column, String, DateTime, ForeignKey, Numeric, Text, Index
from sqlalchemy.orm import relationship
from sqlalchemy import Enum as SqlEnum
from utils.utils import Base
from .schema import BookingStatus, PaymentStatus, TicketValidityStatus


class Booking(Base):
    __tablename__ = "bookings"

    id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
    reservation_id = Column(String(36), ForeignKey("reservations.id", ondelete="RESTRICT"), nullable=False, index=True)
    user_id = Column(String(36), ForeignKey("users.id", ondelete="RESTRICT"), nullable=False, index=True)
    schedule_id = Column(String(36), ForeignKey("schedules.id", ondelete="RESTRICT"), nullable=False, index=True)
    booking_datetime = Column(DateTime, nullable=False, default=datetime.utcnow)
    total_amount = Column(Numeric(12, 2), nullable=False)
    payment_status = Column(SqlEnum(PaymentStatus, name="payment_status_enum"), nullable=False, default=PaymentStatus.PENDING)
    booking_reference = Column(String(12), nullable=False, unique=True, index=True)
    status = Column(SqlEnum(BookingStatus, name="booking_status_enum"), nullable=False, default=BookingStatus.CONFIRMED)
    created_at = Column(DateTime, default=datetime.utcnow, nullable=False)
    updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False)

    reservation = relationship("Reservation", back_populates="bookings")
    user = relationship("User", back_populates="bookings")
    schedule = relationship("Schedule", back_populates="bookings")
    booking_seats = relationship("Bookingseat", back_populates="booking", cascade="all, delete-orphan", passive_deletes=True)
    payments = relationship("Payment", back_populates="booking", cascade="all, delete-orphan", passive_deletes=True)
    ticket = relationship("Ticket", back_populates="booking", uselist=False, cascade="all, delete-orphan", passive_deletes=True)
    cancellation = relationship("Cancellation", back_populates="booking", uselist=False, cascade="all, delete-orphan", passive_deletes=True)

    __table_args__ = (
        Index("ix_bookings_user_created", "user_id", "created_at"),
        Index("ix_bookings_schedule_status", "schedule_id", "status"),
    )


class Bookingseat(Base):
    __tablename__ = "booking_seats"

    id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
    booking_id = Column(String(36), ForeignKey("bookings.id", ondelete="CASCADE"), nullable=False, index=True)
    seat_id = Column(String(36), ForeignKey("seats.id", ondelete="RESTRICT"), nullable=False, index=True)
    seat_number = Column(String(10), nullable=False)
    created_at = Column(DateTime, default=datetime.utcnow, nullable=False)
    updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False)

    booking = relationship("Booking", back_populates="booking_seats")
    seat = relationship("Seat", back_populates="booking_seats")


class Ticket(Base):
    __tablename__ = "tickets"

    id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
    booking_id = Column(String(36), ForeignKey("bookings.id", ondelete="CASCADE"), nullable=False, unique=True, index=True)
    ticket_number = Column(String(20), nullable=False, unique=True, index=True)
    qr_code = Column(Text, nullable=False)
    issue_datetime = Column(DateTime, nullable=False, default=datetime.utcnow)
    validity_status = Column(SqlEnum(TicketValidityStatus, name="ticket_validity_status_enum"), nullable=False, default=TicketValidityStatus.VALID)
    created_at = Column(DateTime, default=datetime.utcnow, nullable=False)
    updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False)

    booking = relationship("Booking", back_populates="ticket")