import hashlib

import emoji
from django.core.cache import cache
from django.db import models
from django.db.models import Q
from django.urls import reverse
from django.utils.translation import gettext_lazy as _
from django_ckeditor_5.fields import CKEditor5Field

from ..models.utils import no_slash_validator, remove_accents


class Tag(models.Model):
    name = models.CharField(
        verbose_name=_("Name"),
        help_text=_("Tag name"),
        max_length=512,
        unique=True,
        validators=[no_slash_validator],
    )

    description = CKEditor5Field(
        verbose_name=_("Description"),
        help_text=_("Description of the tag"),
        blank=True,
        null=True,
    )

    message = CKEditor5Field(
        verbose_name=_("Message"),
        help_text=_(
            "Message displayed to the user on each event associated with this tag."
        ),
        blank=True,
        null=True,
    )

    principal = models.BooleanField(
        verbose_name=_("Principal"),
        help_text=_(
            "This tag is highlighted as a main tag for visitors, particularly in the filter."
        ),
        default=False,
    )

    in_excluded_suggestions = models.BooleanField(
        verbose_name=_("In excluded suggestions"),
        help_text=_("This tag will be part of the excluded suggestions."),
        default=False,
    )

    in_included_suggestions = models.BooleanField(
        verbose_name=_("In included suggestions"),
        help_text=_("This tag will be part of the included suggestions."),
        default=False,
    )

    class Meta:
        verbose_name = _("Tag")
        verbose_name_plural = _("Tags")
        indexes = [
            models.Index(fields=["name"]),
        ]

    def get_absolute_url(self):
        return reverse("view_tag", kwargs={"t": self.name})

    @classmethod
    def clear_cache(cls):
        for exclude in [False, True]:
            for include in [False, True]:
                for nb_suggestions in [10]:
                    id_cache = (
                        "all_tags "
                        + str(exclude)
                        + " "
                        + str(include)
                        + " "
                        + str(nb_suggestions)
                    )
                    id_cache = hashlib.md5(id_cache.encode("utf8")).hexdigest()
                    cache.delete(id_cache)

    def get_tag_groups(nb_suggestions=10, exclude=False, include=False, all=False):
        id_cache = (
            "all_tags " + str(exclude) + " " + str(include) + " " + str(nb_suggestions)
        )
        id_cache = hashlib.md5(id_cache.encode("utf8")).hexdigest()
        result = cache.get(id_cache)

        if not result:
            from ..models.event import Event

            free_tags = Event.get_all_tags(False)
            f_tags = [t["tag"] for t in free_tags]

            obj_tags = Tag.objects

            if all:
                obj_tags = obj_tags.filter(
                    Q(in_excluded_suggestions=True)
                    | Q(in_included_suggestions=True)
                    | Q(principal=True)
                )
            else:
                if exclude:
                    obj_tags = obj_tags.filter(Q(in_excluded_suggestions=True))
                if include:
                    obj_tags = obj_tags.filter(
                        Q(in_included_suggestions=True) | Q(principal=True)
                    )

                if not exclude and not include:
                    obj_tags = obj_tags.filter(principal=True)

            obj_tags = obj_tags.values_list("name", flat=True)

            if len(obj_tags) > nb_suggestions:
                nb_suggestions = len(obj_tags)

            tags = [
                {
                    "tag": t["tag"],
                    "count": 1000000 if t["tag"] in obj_tags else t["count"],
                }
                for t in free_tags
            ]
            tags += [
                {"tag": o, "count": 0}
                for o in Tag.objects.filter(~Q(name__in=f_tags)).values_list(
                    "name", flat=True
                )
            ]

            tags.sort(key=lambda x: -x["count"])

            tags1 = tags[0:nb_suggestions]
            tags1.sort(
                key=lambda x: emoji.demojize(
                    remove_accents(x["tag"]).lower(), delimiters=("000", "")
                )
            )
            tags2 = tags[nb_suggestions:]
            tags2.sort(
                key=lambda x: emoji.demojize(
                    remove_accents(x["tag"]).lower(), delimiters=("000", "")
                )
            )

            result = (
                (_("Suggestions"), [(t["tag"], t["tag"]) for t in tags1]),
                (_("Others"), [(t["tag"], t["tag"]) for t in tags2]),
            )

            cache.set(id_cache, result, 3000)  # 50mn
        return result

    def __str__(self):
        return self.name
