from django.conf import settings
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from django.db import models
from django.db.models import Avg


class Rating(models.Model):
    score = models.PositiveSmallIntegerField(choices=[(i, str(i)) for i in range(1, 6)], verbose_name="Puan")
    comment = models.TextField(blank=True, null=True, verbose_name="Yorum")
    
    # Generic Relation Fields
    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
    object_id = models.PositiveIntegerField()
    content_object = GenericForeignKey('content_type', 'object_id')

    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='ratings')
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        unique_together = ('content_type', 'object_id', 'user')  # Bir kullanıcı bir şeye sadece bir kez oy verebilir
        ordering = ['-created_at']
        verbose_name = "Değerlendirme"
        verbose_name_plural = "Değerlendirmeler"

    def __str__(self):
        return f"{self.score} - {self.content_object}"


# Bu Mixin'i oylanabilir olmasını istediğiniz modellere miras (inherit) verebilirsiniz.
class RateableMixin:
    @property
    def average_rating(self):
        # İlgili nesneye ait tüm oyların ortalamasını alır
        ratings = Rating.objects.filter(
            content_type=ContentType.objects.get_for_model(self),
            object_id=self.id
        )
        return ratings.aggregate(Avg('score'))['score__avg'] or 0.0

    @property
    def rating_count(self):
        # Toplam oy sayısını döndürür
        return Rating.objects.filter(
            content_type=ContentType.objects.get_for_model(self),
            object_id=self.id
        ).count()
