from django.db import models
from django.db.models.aggregates import Sum
from django.db.models.functions import Coalesce
from django.conf import settings
from django.urls import reverse
from django.template.loader import render_to_string
from django.dispatch import receiver
from django.utils.translation import get_language
from constance import config
from tinymce import HTMLField

def get_internationalized(obj_set, prop_name):
    obj = obj_set.filter(language=get_language()).first()
    if obj:
        return getattr(obj, prop_name)
    return ""


class KbCategory(models.Model):
    slug = models.SlugField()
    internal_name = models.CharField("Internal name", max_length=100)

    def get_absolute_url(self):
        return reverse('help:kb_category', kwargs=dict(category=self.slug))

    def get_top_entries(self, n=None):
        n = n or config.KB_MAX_TOP_ENTRIES
        return KbEntry.objects.get_top(n, category=self)

    def get_entry_count(self):
        return self.entry_set.filter(internal=False).count()

    def __str__(self):
        return self.name

    @property
    def name(self):
        return get_internationalized(self.name_set, 'name')
    @property
    def description(self):
        return get_internationalized(self.description_set, 'description')

    class Meta:
        verbose_name = "Knowledgebase Category"
        verbose_name_plural = "Knowledgebase Categories"

class KbCategoryName(models.Model):
    category = models.ForeignKey(KbCategory, on_delete=models.CASCADE,
                                 related_name='name_set')
    language = models.CharField(max_length=2)
    name = models.CharField(max_length=100)

class KbCategoryDescription(models.Model):
    category = models.ForeignKey(KbCategory, on_delete=models.CASCADE,
                                 related_name='description_set')
    language = models.CharField(max_length=2)
    description = models.TextField()


class KbEntry(models.Model):
    create_date = models.DateTimeField(auto_now_add=True, editable=False)
    category = models.ForeignKey(KbCategory, on_delete=models.CASCADE,
                                 related_name='entry_set')
    title = models.CharField(max_length=50)
    internal = models.BooleanField(default=False)

    def vote(self, user, v):
        vote = self.vote_set.filter(user=user).first()
        if vote:
            if vote.vote == v:
                return
            vote.vote = v
            vote.save()
        else:
            v = KbEntryVote(entry=self, user=user, vote=v)
            v.save()

    def get_score(self):
        return self.vote_set.aggregate(Sum('vote'))['vote__sum'] or 0

    def get_vote_count(self):
        return self.vote_set.count()

    def get_absolute_url(self):
        return reverse('help:kb_entry', kwargs=dict(category=self.category.slug, entry=self.id))


    @property
    def question(self):
        return self.question_set.filter(language=get_language()).first().question
    @property
    def answer(self):
        return self.answer_set.filter(language=get_language()).first().answer

    def __str__(self):
        return self.question

    class Meta:
        verbose_name = "Knowledgebase Entry"
        verbose_name_plural = "Knowledgebase Entries"

    class KbEntryManager(models.Manager):
        def get_top(self, n, **kwargs):
            return (self.filter(internal=False, **kwargs)
                    .annotate(score=Coalesce(Sum('vote_set__vote'), 0))
                    .order_by('-score', 'id')
                    [:n])

    objects = KbEntryManager()


class KbEntryQuestion(models.Model):
    entry = models.ForeignKey(KbEntry, on_delete=models.CASCADE,
                              related_name='question_set')
    language = models.CharField(max_length=2)
    question = models.CharField(max_length=200)

class KbEntryAnswer(models.Model):
    entry = models.ForeignKey(KbEntry, on_delete=models.CASCADE,
                              related_name='answer_set')
    language = models.CharField(max_length=2)
    answer = HTMLField()

class KbEntryVote(models.Model):
    entry = models.ForeignKey(KbEntry, on_delete=models.CASCADE,
                              related_name='vote_set')
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET_NULL,
                             null=True)
    create_date = models.DateTimeField(auto_now_add=True, editable=False)
    vote = models.IntegerField()

    def __str__(self):
        return 'Vote %+d on %s by %s' % (self.vote, self.entry, self.user)

    class Meta:
        verbose_name = "Knowledgebase Entry Vote"

