import uuid
from datetime import datetime
from sqlalchemy import Column, String, Boolean, DateTime, Date, Integer, Float, ForeignKey, Text, ARRAY
from sqlalchemy.orm import relationship
from sqlalchemy import Enum as SqlEnum
from utils.utils import Base


class User(Base):
    __tablename__ = "users"

    id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
    email = Column(String(255), unique=True, nullable=False, index=True)
    password_hash = Column(String(255), nullable=False)
    role = Column(String(50), nullable=False, index=True)
    first_name = Column(String(100), nullable=False)
    last_name = Column(String(100), nullable=False)
    phone = Column(String(50), nullable=True)
    is_active = Column(Boolean, default=True, nullable=False)
    last_login_at = Column(DateTime, nullable=True)
    created_at = Column(DateTime, default=datetime.utcnow, nullable=False)
    updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False)

    customer = relationship("Customer", back_populates="user", uselist=False)
    tour_guide = relationship("Tourguide", back_populates="user", uselist=False)
    service_provider = relationship("Serviceprovider", back_populates="user", uselist=False)
    bookings_as_agent = relationship("Booking", foreign_keys="[Booking.booking_agent_id]", back_populates="booking_agent")
    expenses_submitted = relationship("Expense", foreign_keys="[Expense.submitted_by]", back_populates="submitter")
    expenses_approved = relationship("Expense", foreign_keys="[Expense.approved_by]", back_populates="approver")
    cancellation_requests_processed = relationship("Cancellationrequest", foreign_keys="[Cancellationrequest.processed_by]", back_populates="processor")
    commissions = relationship("Commission", foreign_keys="[Commission.booking_agent_id]", back_populates="booking_agent")
    notifications = relationship("Notification", back_populates="user")
    documents_uploaded = relationship("Document", foreign_keys="[Document.uploaded_by]", back_populates="uploader")


class Customer(Base):
    __tablename__ = "customers"

    id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
    user_id = Column(String(36), ForeignKey("users.id", ondelete="CASCADE"), unique=True, nullable=False, index=True)
    date_of_birth = Column(Date, nullable=True)
    nationality = Column(String(100), nullable=True)
    passport_number = Column(String(50), nullable=True)
    passport_expiry = Column(Date, nullable=True)
    emergency_contact_name = Column(String(100), nullable=True)
    emergency_contact_phone = Column(String(50), nullable=True)
    address_line1 = Column(String(255), nullable=True)
    address_line2 = Column(String(255), nullable=True)
    city = Column(String(100), nullable=True)
    state = Column(String(100), nullable=True)
    country = Column(String(100), nullable=True)
    postal_code = Column(String(20), nullable=True)
    loyalty_status = Column(String(50), nullable=True)
    loyalty_points = Column(Integer, default=0, nullable=False)
    preferences = Column(Text, nullable=True)
    created_at = Column(DateTime, default=datetime.utcnow, nullable=False)
    updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False)

    user = relationship("User", back_populates="customer")
    bookings = relationship("Booking", back_populates="customer")
    reviews = relationship("Review", back_populates="customer")
    cancellation_requests = relationship("Cancellationrequest", back_populates="customer")
    documents = relationship("Document", foreign_keys="[Document.customer_id]", back_populates="customer")


class Tourguide(Base):
    __tablename__ = "tour_guides"

    id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
    user_id = Column(String(36), ForeignKey("users.id", ondelete="CASCADE"), unique=True, nullable=False, index=True)
    languages_spoken = Column(ARRAY(String), nullable=False)
    specializations = Column(ARRAY(String), nullable=True)
    certifications = Column(Text, nullable=True)
    license_number = Column(String(50), nullable=True)
    license_expiry = Column(Date, nullable=True)
    years_of_experience = Column(Integer, nullable=True)
    bio = Column(Text, nullable=True)
    rating = Column(Float, nullable=True)
    total_tours_conducted = Column(Integer, default=0, nullable=False)
    is_available = Column(Boolean, default=True, nullable=False)
    created_at = Column(DateTime, default=datetime.utcnow, nullable=False)
    updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False)

    user = relationship("User", back_populates="tour_guide")
    tour_schedules = relationship("Tourschedule", back_populates="tour_guide")
    reviews = relationship("Review", back_populates="tour_guide")


class Serviceprovider(Base):
    __tablename__ = "service_providers"

    id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
    user_id = Column(String(36), ForeignKey("users.id", ondelete="CASCADE"), unique=True, nullable=False, index=True)
    company_name = Column(String(255), nullable=False)
    service_type = Column(String(50), nullable=False, index=True)
    registration_number = Column(String(100), nullable=True)
    tax_id = Column(String(100), nullable=True)
    contact_person = Column(String(100), nullable=True)
    contact_email = Column(String(255), nullable=True)
    contact_phone = Column(String(50), nullable=True)
    address_line1 = Column(String(255), nullable=True)
    address_line2 = Column(String(255), nullable=True)
    city = Column(String(100), nullable=True)
    state = Column(String(100), nullable=True)
    country = Column(String(100), nullable=True)
    postal_code = Column(String(20), nullable=True)
    contract_start_date = Column(Date, nullable=True)
    contract_end_date = Column(Date, nullable=True)
    payment_terms = Column(Text, nullable=True)
    rating = Column(Float, nullable=True)
    is_verified = Column(Boolean, default=False, nullable=False)
    created_at = Column(DateTime, default=datetime.utcnow, nullable=False)
    updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False)

    user = relationship("User", back_populates="service_provider")
    hotels = relationship("Hotel", back_populates="service_provider")
    transportations = relationship("Transportation", back_populates="service_provider")