"""Tag app models."""
from django.contrib.contenttypes.models import ContentType
from django.db import models
from django.utils.translation import gettext_lazy as _

from configuration.models import TranslationSettings
from location.models import Country
from utils.models import IndexJSON


class TagQuerySet(models.QuerySet):

    def for_news(self):
        """Select chosen tags for news."""
        return self.filter(category__news_types__isnull=False)

    def for_establishments(self):
        """Select chosen tags for establishments."""
        return self.filter(models.Q(category__establishment_types__isnull=False) |
                           models.Q(category__establishment_subtypes__isnull=False))

    def by_category_index_name(self, index_name):
        return self.filter(category__index_name=index_name)

    def order_by_priority(self):
        return self.order_by('chosentagsettings__priority')

    def by_establishment_type(self, index_name):
        return self.filter(category__establishment_types__index_name=index_name)


class Tag(models.Model):
    """Tag model."""

    value = models.CharField(_('indexing name'), max_length=255, blank=True, db_index=True,
                             null=True, default=None)
    category = models.ForeignKey('TagCategory', on_delete=models.CASCADE,
                                 null=True, related_name='tags',
                                 verbose_name=_('Category'))
    chosen_tag_settings = models.ManyToManyField(Country, through='ChosenTagSettings')
    priority = models.PositiveIntegerField(null=True, default=0)

    # It does not make sense since in the old base another structure with duplicates
    old_id = models.PositiveIntegerField(_('old id'), blank=True, null=True, default=None)

    old_id_meta_product = models.PositiveIntegerField(_('old id metadata product'),
                                                      blank=True, null=True, default=None)
    translation = models.ForeignKey('translation.SiteInterfaceDictionary', on_delete=models.SET_NULL,
                                    null=True, related_name='tag', verbose_name=_('Translation'))

    @property
    def label_indexing(self):
        base_dict = self.translation.text if self.translation and isinstance(self.translation.text, dict) else {}
        index = IndexJSON()
        for k, v in base_dict.items():
            setattr(index, k, v)
        return index

    objects = TagQuerySet.as_manager()

    class Meta:
        """Meta class."""

        verbose_name = _('Tag')
        verbose_name_plural = _('Tags')

    def __str__(self):
        return f'Tag (id = {self.id}, label_translated = {self.value})'


class ChosenTagSettingsQuerySet(models.QuerySet):

    def by_country_code(self, country_code):
        return self.filter(country__code=country_code)


class ChosenTagSettings(models.Model):
    """Chosen tag model."""

    tag = models.ForeignKey(Tag, on_delete=models.PROTECT)
    country = models.ForeignKey(Country, on_delete=models.PROTECT)
    priority = models.IntegerField(null=False, default=0)

    objects = ChosenTagSettingsQuerySet.as_manager()

    class Meta:
        """Meta class."""

        verbose_name = _('Chosen tag')
        verbose_name_plural = _('Chosen tags')


class TagCategoryQuerySet(models.QuerySet):
    """Extended queryset for TagCategory model."""

    def with_base_related(self):
        """Select related objects."""
        return self.prefetch_related('tags',  'tags__translation').select_related('translation')

    def with_extended_related(self):
        """Select related objects."""
        return self.select_related('country')

    def for_news(self):
        """Select tag categories for news."""
        return self.filter(news_types__isnull=False)

    def for_establishments(self):
        """Select tag categories for establishments."""
        return self.filter(models.Q(establishment_types__isnull=False) |
                           models.Q(establishment_subtypes__isnull=False))

    def by_establishment_type(self, index_name):
        """Filter by establishment type index name."""
        return self.filter(establishment_types__index_name=index_name)

    def by_product_type(self, index_name):
        """Filter by product type index name."""
        return self.filter(tags__products__product_type__index_name=index_name)

    def wine_tags_category(self):
        return self.filter(index_name='wine-color')

    def with_tags(self, switcher=True):
        """Filter by existing tags."""
        return self.exclude(tags__isnull=switcher)


class TagCategory(models.Model):
    """Tag base category model."""

    STRING = 'string'
    LIST = 'list'
    INTEGER = 'integer'
    FLOAT = 'float'
    PERCENTAGE = 'percentage'
    BOOLEAN = 'bool'

    VALUE_TYPE_CHOICES = (
        (STRING, _('string')),
        (LIST, _('list')),
        (INTEGER, _('integer')),
        (FLOAT, _('float')),
        (PERCENTAGE, _('percentage')),
        (BOOLEAN, _('boolean')),
    )
    country = models.ForeignKey('location.Country',
                                on_delete=models.SET_NULL, null=True,
                                default=None)
    public = models.BooleanField(default=False)
    index_name = models.CharField(max_length=255, blank=True, null=True,
                                  verbose_name=_('indexing name'), unique=True)

    value_type = models.CharField(_('value type'), max_length=255,
                                  choices=VALUE_TYPE_CHOICES, default=LIST, )
    old_id = models.IntegerField(blank=True, null=True)
    translation = models.OneToOneField('translation.SiteInterfaceDictionary', on_delete=models.SET_NULL,
                                       null=True, related_name='tag_category', verbose_name=_('Translation'))

    @property
    def label_indexing(self):
        base_dict = self.translation.text if self.translation and isinstance(self.translation.text, dict) else {}
        index = IndexJSON()
        for k, v in base_dict.items():
            setattr(index, k, v)
        return index

    objects = TagCategoryQuerySet.as_manager()

    class Meta:
        """Meta class."""

        verbose_name = _('Tag category')
        verbose_name_plural = _('Tag categories')

    def __str__(self):
        return self.index_name
