from django.db import models
import uuid
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
from django.conf import settings
# Create your models here.

# ✅ Custom user manager to handle user creation properly
class UserManager(BaseUserManager):
    def create_user(self, username, email, password=None, **extra_fields):
        if not username:
            raise ValueError("The Username field is required")
        if not email:
            raise ValueError("The Email field is required")

        email = self.normalize_email(email)
        user = self.model(username=username, email=email, **extra_fields)
        user.set_password(password)  # ✅ Hash password before saving
        user.save(using=self._db)
        return user

    def create_superuser(self, username, email, password=None, **extra_fields):
        extra_fields.setdefault("user_role", "admin")
        return self.create_user(username, email, password, **extra_fields)

# ✅ Your `User` model (acts as Django’s user model)
class User(AbstractBaseUser):  
    ROLE_CHOICES = [
        ('admin', 'Admin'),
        ('user', 'User'),
        ('owner', 'Owner'),
    ]
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    full_name = models.CharField(max_length=255)
    username = models.CharField(max_length=100, unique=True)
    email = models.EmailField()
    phone = models.CharField(max_length=15, blank=True, null=True)
    address = models.TextField(blank=True, null=True)
    user_role = models.CharField(max_length=10, choices=ROLE_CHOICES, default='user')
    created_at = models.DateTimeField(auto_now_add=True)
    profile_picture = models.ImageField(upload_to='profile_pics/', default='profile_pics/default.gif')

    # ✅ Required fields for Django authentication
    is_active = models.BooleanField(default=True)
    is_staff = models.BooleanField(default=False)

    objects = UserManager()  # ✅ Attach the custom user manager

    USERNAME_FIELD = "username"  # ✅ Use username for authentication
    REQUIRED_FIELDS = ["email"]  # ✅ Email is required

    def __str__(self):
        return self.username
    
class Notification(models.Model):
    CATEGORY_CHOICES = [
        ('user_event', 'User Event'),
        ('system_alert', 'System Alert'),
        ('general', 'General'),
    ]
    ROLE_CHOICES = [
        ('user', 'User'),
        ('admin', 'Admin'),
        ('owner', 'Owner'),
    ]

    title = models.CharField(max_length=255)
    message = models.TextField()
    category = models.CharField(max_length=50, choices=CATEGORY_CHOICES, default='general')
    role_visibility = models.CharField(max_length=50, choices=ROLE_CHOICES, default='admin')
    is_viewed = models.BooleanField(default=False)
    created_by = models.CharField(max_length=50, default='user', null=True, blank=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)  # auto-updated on save
    recipient_user = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True, related_name="notifications_received")
    action_url = models.CharField(
        max_length=500,
        null=True,
        blank=True,
        help_text="URL to go to when notification is clicked"
    )
    class Meta:
        ordering = ['-created_at']  # Newest first by default
        db_table = 'notifications'  # Optional: clean table name

    def __str__(self):
        return f"{self.title} → {self.role_visibility.upper()} | By: {self.created_by.username}"
    
# Dzongkhag table
class Dzongkhag(models.Model):
    dzo_id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=100)
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.name

# Gewog table (linked to Dzongkhag)
class Gewog(models.Model):
    gewog_id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=100)
    dzongkhag = models.ForeignKey(Dzongkhag, on_delete=models.CASCADE, related_name='gewogs')
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return f"{self.name} ({self.dzongkhag.name})"

# Village table (linked to both Dzongkhag and Gewog)
class Village(models.Model):
    village_id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=100)
    dzongkhag = models.ForeignKey(Dzongkhag, on_delete=models.CASCADE, related_name='villages')
    gewog = models.ForeignKey(Gewog, on_delete=models.CASCADE, related_name='villages')
    created_at = models.DateTimeField(auto_now_add=True)
    def __str__(self):
        return f"{self.name} - {self.gewog.name}, {self.dzongkhag.name}"
    
class Hotel(models.Model):
    name = models.CharField(max_length=255)
    location = models.CharField(max_length=255)
    description = models.TextField(blank=True, null=True)
    dzongkhag = models.ForeignKey(Dzongkhag, on_delete=models.SET_NULL, null=True, related_name="hotels")
    gewog = models.ForeignKey(Gewog, on_delete=models.SET_NULL, null=True, related_name="hotels")
    village = models.ForeignKey(Village, on_delete=models.SET_NULL, null=True, related_name="hotels")
    contact_number = models.CharField(max_length=20)
    email = models.EmailField(blank=True, null=True)
    home_image = models.ImageField(upload_to="hotels/", blank=True, null=True, default="hotels/default_hotel.jpg")
    hotel_image1 = models.ImageField(upload_to="hotels/", blank=True, null=True, default="hotels/default_hotel.jpg")
    hotel_image2 = models.ImageField(upload_to="hotels/", blank=True, null=True, default="hotels/default_hotel.jpg")
    hotel_image3 = models.ImageField(upload_to="hotels/", blank=True, null=True, default="hotels/default_hotel.jpg")
    # Extra details
    total_rooms = models.PositiveIntegerField(default=0)
    available_rooms = models.PositiveIntegerField(default=0)
    hotel_owner = models.CharField(max_length=255, blank=True, null=True)
    created_at = models.DateTimeField(auto_now_add=True)
    room_choices = (
        ("single", "Single Room"),
        ("double", "Double Room"),
        ("twin", "Twin Room"),
        ("triple", "Triple Room"),
        ("quad", "Quad Room"),
        ("queen", "Queen Room"),
        ("king", "King Room"),
        ("suite", "Suite"),
        ("penthouse", "Penthouse"),
    )
    room_types = models.CharField(max_length=20, choices=room_choices, default="Active")
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='hotels', null=True, blank=True)
    def get_gallery_images(self):
        images = [self.home_image, self.hotel_image1, self.hotel_image2, self.hotel_image3]
        return [img for img in images if img and hasattr(img, 'url')]
    def __str__(self):
        return self.name
    
class RoomType(models.Model):
    ROOM_CHOICES = (
        ("single", "Single Room"),
        ("double", "Double Room"),
        ("twin", "Twin Room"),
        ("triple", "Triple Room"),
        ("quad", "Quad Room"),
        ("queen", "Queen Room"),
        ("king", "King Room"),
        ("suite", "Suite"),
        ("penthouse", "Penthouse"),
    )

    hotel = models.ForeignKey("Hotel", on_delete=models.CASCADE, related_name="hotel_room_types")
    room_type = models.CharField(max_length=20, choices=ROOM_CHOICES, default="single")
    description = models.TextField(blank=True, null=True)
    price_per_night = models.DecimalField(max_digits=10, decimal_places=2, default=0)
    total_rooms = models.PositiveIntegerField(default=1)
    created_at = models.DateTimeField(auto_now_add=True)
    room_image = models.ImageField(upload_to="room_types/", blank=True, null=True, default="hotels/default_hotel.jpg")

    def __str__(self):
        return f"{self.get_room_type_display()} ({self.hotel.name})"

# models.py
class Booking(models.Model):
    hotel = models.ForeignKey(Hotel, on_delete=models.CASCADE, related_name="bookings")
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="bookings")
    room_selected = models.ForeignKey(
        RoomType,
        on_delete=models.CASCADE,
        related_name="bookings",
        null=True,
        blank=True
    )
    check_in = models.DateField()
    check_out = models.DateField()
    number_of_rooms = models.PositiveIntegerField(default=1)
    number_of_guests = models.PositiveIntegerField(default=1)
    created_at = models.DateTimeField(auto_now_add=True)
    status_choices = (
        ("pending", "Pending"),
        ("confirmed", "Confirmed"),
        ("cancelled", "Cancelled"),
    )
    status = models.CharField(max_length=20, choices=status_choices, default="pending")

    def __str__(self):
        return f"{self.user.username} - {self.hotel.name} ({self.status})"
    
class Message(models.Model):
    sender = models.ForeignKey(User, on_delete=models.CASCADE, related_name="sent_messages")
    receiver = models.ForeignKey(User, on_delete=models.CASCADE, related_name="received_messages")
    subject = models.CharField(max_length=200, blank=True, null=True)
    message = models.TextField()
    read = models.BooleanField(default=False)  # Mark as read
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return f"From {self.sender.username} to {self.receiver.username}: {self.subject or self.message[:30]}"

    class Meta:
        ordering = ['-created_at']  

class Review(models.Model):
    hotel = models.ForeignKey(Hotel, on_delete=models.CASCADE, related_name="reviews")
    room_type = models.ForeignKey(RoomType, on_delete=models.CASCADE, related_name="reviews", null=True, blank=True)
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="reviews")
    booking = models.ForeignKey(Booking, on_delete=models.CASCADE, related_name="reviews", null=True, blank=True)  # 👈 ADD THIS
    rating = models.PositiveSmallIntegerField(
        choices=[(i, str(i)) for i in range(1, 6)],
        default=5
    )
    comment = models.TextField(blank=True, null=True)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ['-created_at']
        db_table = 'reviews'
        unique_together = ['user', 'booking']  # 👈 Prevents duplicates at DB level too!

    def __str__(self):
        return f"{self.user.username} → {self.hotel.name} ({self.rating}★)"
    
#gallery table section
class GalleryCategory(models.Model):
    name = models.CharField(max_length=50, unique=True)  # e.g., "Spa Sanctuary"
    slug = models.SlugField(max_length=50, unique=True, blank=True)  # auto-generated URL-friendly version
    description = models.TextField(blank=True)

    class Meta:
        verbose_name_plural = "Gallery Categories"
        ordering = ['name']

    def __str__(self):
        return self.name

    def save(self, *args, **kwargs):
        if not self.slug:
            from django.utils.text import slugify
            self.slug = slugify(self.name)
        super().save(*args, **kwargs)

class GalleryImage(models.Model):
    title = models.CharField(max_length=100)
    description = models.TextField(blank=True)
    category = models.ForeignKey(GalleryCategory, on_delete=models.CASCADE, related_name='images')
    image = models.ImageField(upload_to='gallery_images/')
    uploaded_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ['-uploaded_at']

    def __str__(self):
        return self.title