from django.db.models.signals import post_save
from django.dispatch import receiver
import qrcode
from io import BytesIO
from django.core.files import File
from django.db import models
from django.urls import reverse
from django.conf import settings
from django.contrib.auth.models import User


class Wishlist(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    product = models.ForeignKey("Product", on_delete=models.CASCADE)
    added_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        unique_together = ('user', 'product')

    def __str__(self):
        return f"{self.user.username} - {self.product.name}"


class Review(models.Model):
    user = models.ForeignKey(
        User, on_delete=models.CASCADE, related_name="reviews")
    product = models.ForeignKey(
        'Product', on_delete=models.CASCADE, related_name="reviews")
    rating = models.IntegerField(
        choices=[(i, i) for i in range(1, 6)], default=5)
    comment = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ['-created_at']

    def __str__(self):
        return f"Review by {self.user.username} for {self.product.name}"

# ✅ New Model for Review Replies


class ReviewReply(models.Model):
    review = models.OneToOneField(
        Review, on_delete=models.CASCADE, related_name="reply")
    admin = models.ForeignKey(
        User, on_delete=models.CASCADE, limit_choices_to={'is_staff': True})
    reply_text = models.TextField()
    replied_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return f"Reply by {self.admin.username} to {self.review.user.username}'s review"


class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    image = models.ImageField(
        upload_to='profile_pics/', default='default_avatar.png')

    def __str__(self):
        return f'{self.user.username} Profile'


@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
    if created:
        Profile.objects.create(user=instance)


@receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
    instance.profile.save()


class Testimonial(models.Model):
    user = models.ForeignKey(
        User, on_delete=models.CASCADE, related_name="testimonials")  # Link to user
    message = models.TextField()
    rating = models.IntegerField(
        choices=[(i, i) for i in range(1, 6)], default=5)  # Rating (1-5)
    created_at = models.DateTimeField(auto_now_add=True)
    approved = models.BooleanField(default=False)  # Admin must approve

    class Meta:
        ordering = ['-created_at']

    def __str__(self):
        return f"Testimonial from {self.user.username}"


class Blog(models.Model):
    title = models.CharField(max_length=200)
    content = models.TextField()
    image = models.ImageField(upload_to='blog_images/', blank=True, null=True)
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.title


class Slide(models.Model):
    name = models.CharField(max_length=100)
    description = models.TextField()
    # optional if you want an image
    image = models.ImageField(upload_to='slides/')

    def __str__(self):
        return self.name


class Category(models.Model):
    STATUS_CHOICES = [
        ('active', 'Active'),
        ('inactive', 'Inactive'),
    ]
    name = models.CharField(max_length=100)
    status = models.CharField(
        max_length=10, choices=STATUS_CHOICES, default='active', blank=True, null=True)
    created_at = models.DateTimeField(auto_now_add=True, blank=True, null=True)

    class Meta:
        permissions = [
            ("bulk_delete", "Can delete bulk?"),
            ("download_pdf", "Can download PDF?"),
            ("download_excel", "Can download Excel?"),
            ("bulk_status", "Can can update status?"),
        ]

    def __str__(self):
        return self.name


class Product(models.Model):
    name = models.CharField(max_length=200)
    category = models.ForeignKey(Category, on_delete=models.PROTECT)
    description = models.TextField()
    price = models.DecimalField(max_digits=10, decimal_places=2)
    stock = models.PositiveIntegerField(default=0)
    rating = models.DecimalField(max_digits=3, decimal_places=2, default=0.0)
    image = models.ImageField(upload_to='products/')
    qr_code = models.ImageField(upload_to='qrcodes/', blank=True)
    is_featured = models.BooleanField(default=False)

    class Meta:
        permissions = [
            ("bulk_delete", "Can delete bulk?"),
            ("download_pdf", "Can download PDF?"),
            ("download_excel", "Can download Excel?"),
            ("bulk_status", "Can can update status?"),
        ]

    def __str__(self):
        return self.name

    def get_absolute_url(self):
        return reverse('product_detail', args=[str(self.id)])

    def save(self, *args, **kwargs):
        # Save the instance to get a primary key.
        super().save(*args, **kwargs)
        if not self.qr_code:
            full_url = f"{settings.SITE_URL}{self.get_absolute_url()}"
            qr = qrcode.QRCode(version=1, box_size=10, border=5)
            qr.add_data(full_url)
            qr.make(fit=True)
            img = qr.make_image(fill='black', back_color='white')
            buffer = BytesIO()
            img.save(buffer)
            buffer.seek(0)
            self.qr_code.save(f'{self.name}_qrcode.png',
                              File(buffer), save=False)
            super().save(*args, **kwargs)  # Save again to include the QR code.


class Cart(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    items = models.ManyToManyField(Product, through='CartItem')

    def get_total_price(self):
        return sum(item.get_total_price() for item in self.cartitem_set.all())


class CartItem(models.Model):
    cart = models.ForeignKey(Cart, on_delete=models.CASCADE)
    product = models.ForeignKey(Product, on_delete=models.CASCADE)
    quantity = models.PositiveIntegerField(default=1)

    def get_total_price(self):
        return self.product.price * self.quantity


class Order(models.Model):
    STATUS_CHOICES = [
        ('Pending', 'Pending'),
        ('Processing', 'Processing'),
        ('Shipped', 'Shipped'),
        ('Delivered', 'Delivered'),
        ('Cancelled', 'Cancelled'),
    ]

    user = models.ForeignKey(
        User, on_delete=models.CASCADE, null=True, blank=True)  # Guest users allowed
    full_name = models.CharField(max_length=255)
    address = models.TextField()
    phone = models.CharField(max_length=20)
    payment_method = models.CharField(max_length=50)
    total_price = models.DecimalField(max_digits=10, decimal_places=2)
    status = models.CharField(
        max_length=20, choices=STATUS_CHOICES, default='Pending')
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        permissions = [
            ("view_order_details", "Can view order's details?"),
            ("bulk_status", "Can can update status?"),
            ("download_excel", "Can download Excel?"),
            ("download_pdf", "Can download PDF?"),
            ("download_invoice_pdf", "Can download PDF?"),
        ]

    def __str__(self):
        return f"Order {self.id} - {self.full_name} ({self.status})"


class OrderItem(models.Model):
    order = models.ForeignKey(
        Order, related_name="items", on_delete=models.CASCADE)
    product = models.ForeignKey('Product', on_delete=models.CASCADE)
    quantity = models.PositiveIntegerField()
    price = models.DecimalField(max_digits=10, decimal_places=2)

    def get_total_price(self):
        return self.quantity * self.price

    def __str__(self):
        return f"{self.quantity} x {self.product.name} in Order {self.order.id}"


class FAQ(models.Model):
    CATEGORY_CHOICES = [
        ('shipping', 'Shipping'),
        ('payments', 'Payments'),
        ('product', 'Product Info'),
        ('returns', 'Returns'),
    ]
    user = models.ForeignKey(
        User, on_delete=models.CASCADE, related_name="faqs", null=True, blank=True)
    question = models.TextField()
    category = models.CharField(
        max_length=50, choices=CATEGORY_CHOICES, default='product')
    created_at = models.DateTimeField(auto_now_add=True)
    likes = models.ManyToManyField(User, related_name="faq_likes", blank=True)
    dislikes = models.ManyToManyField(
        User, related_name="faq_dislikes", blank=True)

    def total_likes(self):
        return self.likes.count()

    def total_dislikes(self):
        return self.dislikes.count()

    class Meta:
        ordering = ["-created_at"]

    def __str__(self):
        return self.question[:50]


class FAQAnswer(models.Model):
    faq = models.ForeignKey(
        FAQ, on_delete=models.CASCADE, related_name="answers")
    user = models.ForeignKey(
        User, on_delete=models.CASCADE)  # User who answered
    answer = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)
    likes = models.ManyToManyField(
        User, related_name="answer_likes", blank=True)
    dislikes = models.ManyToManyField(
        User, related_name="answer_dislikes", blank=True)

    class Meta:
        ordering = ["-created_at"]

    def total_likes(self):
        return self.likes.count()

    def total_dislikes(self):
        return self.dislikes.count()

    def __str__(self):
        return f"Answer by {self.user.username} on {self.faq.question[:30]}"


class AnswerComment(models.Model):
    answer = models.ForeignKey(
        FAQAnswer, related_name="comments", on_delete=models.CASCADE)
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    comment = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)


class NewsletterSubscriber(models.Model):
    email = models.EmailField(unique=True)
    subscribed_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.email
