from flask_login import UserMixin
from werkzeug.security import generate_password_hash, check_password_hash
from datetime import datetime  
from enum import Enum
from slugify import slugify
from .extensions import db
from sqlalchemy.orm import relationship
from sqlalchemy import Enum as SQLAlchemyEnum

class User(UserMixin, db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(64), unique=True, nullable=False)
    password_hash = db.Column(db.String(128))

    def set_password(self, password):
        self.password_hash = generate_password_hash(password)

    def check_password(self, password):
        return check_password_hash(self.password_hash, password)

class VehicleCategory(Enum):
    Car = 'Car'
    Luxury_Car = 'Luxury Car'
    Van = 'Van'
    Bus = 'Bus'

class Car(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(100), nullable=False)
    capacity = db.Column(db.Integer)
    price_per_day = db.Column(db.Float)
    image = db.Column(db.String(200))
    category = db.Column(SQLAlchemyEnum(VehicleCategory), nullable=False)
    has_ac = db.Column(db.Boolean, default=False)
    has_usb = db.Column(db.Boolean, default=False)
    has_player = db.Column(db.Boolean, default=False)
    has_bluetooth = db.Column(db.Boolean, default=False)
    luggage_space = db.Column(db.String(50))

    def __repr__(self):
        return f'<Car {self.name}>'

class TourType(Enum):
    MULTI_DAY_TOUR = 'Multi-Day Tour'

class TourParentCategory(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(100), nullable=False, unique=True)
    slug = db.Column(db.String(100), nullable=False, unique=True)
    display_in_menu = db.Column(db.Boolean, nullable=False, default=True)
    subcategories = relationship('TourSubCategory', back_populates='parent_category', cascade='all, delete-orphan')

    def __init__(self, *args, **kwargs):
        if 'slug' not in kwargs:
            kwargs['slug'] = slugify(kwargs.get('name', ''))
        super().__init__(*args, **kwargs)

    def __repr__(self):
        return f'<TourParentCategory {self.name}>'

class TourSubCategory(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(100), nullable=False)
    slug = db.Column(db.String(100), nullable=False)
    image = db.Column(db.String(200))
    parent_category_id = db.Column(db.Integer, db.ForeignKey('tour_parent_category.id'), nullable=False)
    parent_category = relationship('TourParentCategory', back_populates='subcategories')
    tours = relationship('Tour', back_populates='subcategory')

    def __init__(self, *args, **kwargs):
        if 'slug' not in kwargs:
            kwargs['slug'] = slugify(kwargs.get('name', ''))
        super().__init__(*args, **kwargs)

    def __repr__(self):
        return f'<TourSubCategory {self.name}>'

class Tour(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(100), nullable=False)
    subtitle = db.Column(db.String(200))
    description = db.Column(db.Text)
    itinerary = db.Column(db.Text, nullable=False)
    inclusions = db.Column(db.Text)
    exclusions = db.Column(db.Text)
    additional_info = db.Column(db.Text)
    image = db.Column(db.String(255))
    views = db.Column(db.Integer, default=0)
    subcategory_id = db.Column(db.Integer, db.ForeignKey('tour_sub_category.id'), nullable=False)
    slug = db.Column(db.String(200), unique=True, nullable=False)
    duration = db.Column(db.String(50))
    
    subcategory = relationship('TourSubCategory', back_populates='tours')
    tour_days = relationship('TourDay', back_populates='tour', cascade='all, delete-orphan')

    def __init__(self, *args, **kwargs):
        super(Tour, self).__init__(*args, **kwargs)
        if not self.slug and self.title:
            self.slug = self.generate_slug(self.title)

    def __repr__(self):
        return f'<Tour {self.title}>'

    @staticmethod
    def generate_slug(title):
        base_slug = slugify(title)
        slug = base_slug
        n = 1
        while Tour.query.filter_by(slug=slug).first() is not None:
            slug = f"{base_slug}-{n}"
            n += 1
        return slug

class TourDay(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    tour_id = db.Column(db.Integer, db.ForeignKey('tour.id', ondelete='CASCADE'), nullable=False)
    day_number = db.Column(db.Integer, nullable=False)
    title = db.Column(db.String(100), nullable=False)
    description = db.Column(db.Text, nullable=False)
    tour = relationship('Tour', back_populates='tour_days')

    def __repr__(self):
        return f'<TourDay {self.day_number} of Tour {self.tour_id}>'

class Booking(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    customer_name = db.Column(db.String(100), nullable=False)
    customer_email = db.Column(db.String(120), nullable=False)
    start_date = db.Column(db.Date, nullable=False)
    end_date = db.Column(db.Date, nullable=False)
    car_id = db.Column(db.Integer, db.ForeignKey('car.id'))
    tour_id = db.Column(db.Integer, db.ForeignKey('tour.id'))
    created_at = db.Column(db.DateTime, default=datetime.utcnow)

    car = relationship('Car', backref='bookings')
    tour = relationship('Tour', backref='bookings')

class QuoteRequest(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    first_name = db.Column(db.String(64), nullable=False)
    last_name = db.Column(db.String(64), nullable=False)
    num_adults = db.Column(db.Integer, nullable=False)
    num_children = db.Column(db.Integer, default=0)
    date_from = db.Column(db.Date, nullable=False)
    date_to = db.Column(db.Date, nullable=False)
    country = db.Column(db.String(64), nullable=False)
    email = db.Column(db.String(120), nullable=False)
    phone = db.Column(db.String(20), nullable=False)
    message = db.Column(db.Text)
    car_id = db.Column(db.Integer, db.ForeignKey('car.id'))
    tour_id = db.Column(db.Integer, db.ForeignKey('tour.id'))
    created_at = db.Column(db.DateTime, default=datetime.utcnow)

class Contact(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(100), nullable=False)
    email = db.Column(db.String(120), nullable=False)
    subject = db.Column(db.String(200), nullable=False)
    message = db.Column(db.Text, nullable=False)
    timestamp = db.Column(db.DateTime, default=datetime.utcnow)

    def __repr__(self):
        return f'<Contact {self.name}>'
    
class Blog(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(200), nullable=False)
    slug = db.Column(db.String(200), unique=True, nullable=False)
    content = db.Column(db.Text, nullable=False)
    feature_image = db.Column(db.String(200))
    gallery_image_1 = db.Column(db.String(200))
    gallery_image_2 = db.Column(db.String(200))
    gallery_image_3 = db.Column(db.String(200))
    meta_description = db.Column(db.String(160))
    meta_keywords = db.Column(db.String(200))
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)

    def __init__(self, *args, **kwargs):
        if 'slug' not in kwargs:
            kwargs['slug'] = slugify(kwargs.get('title', ''))
        super().__init__(*args, **kwargs)

    def __repr__(self):
        return f'<Blog {self.title}>'