from django.db import models
from django.urls import reverse
from django.utils.html import strip_tags
from imagekit.models import ProcessedImageField
from imagekit.processors import ResizeToFit

from .. import helpers
from .utils import category_thumb_path, generate_uid


class Category(models.Model):
    """A Category base model"""

    uid = models.CharField(unique=True, max_length=36, default=generate_uid)

    add_date = models.DateTimeField(auto_now_add=True)

    title = models.CharField(max_length=100, db_index=True)

    description = models.TextField(blank=True)

    user = models.ForeignKey("users.User", on_delete=models.CASCADE, blank=True, null=True)

    is_global = models.BooleanField(default=False, help_text="global categories or user specific")

    media_count = models.IntegerField(default=0, help_text="number of media")

    thumbnail = ProcessedImageField(
        upload_to=category_thumb_path,
        processors=[ResizeToFit(width=344, height=None)],
        format="JPEG",
        options={"quality": 85},
        blank=True,
    )

    listings_thumbnail = models.CharField(max_length=400, blank=True, null=True, help_text="Thumbnail to show on listings")

    is_rbac_category = models.BooleanField(default=False, db_index=True, help_text='If access to Category is controlled by role based membership of Groups')

    identity_provider = models.ForeignKey(
        'socialaccount.SocialApp',
        blank=True,
        null=True,
        on_delete=models.CASCADE,
        related_name='categories',
        help_text='If category is related with a specific Identity Provider',
        verbose_name='IDP Config Name',
    )

    # LTI/LMS integration fields
    is_lms_course = models.BooleanField(default=False, db_index=True, help_text='Whether this category represents an LMS course')

    lti_platform = models.ForeignKey('lti.LTIPlatform', blank=True, null=True, on_delete=models.SET_NULL, related_name='categories', help_text='LTI Platform if this is an LTI course')

    lti_context_id = models.CharField(max_length=255, blank=True, db_index=True, help_text='LTI context ID from platform')

    def __str__(self):
        return self.title

    class Meta:
        ordering = ["title"]
        verbose_name_plural = "Categories"

    def get_absolute_url(self):
        return f"{reverse('search')}?c={self.title}"

    def update_category_media(self):
        """Set media_count"""

        # Always set number of Category the total number of media
        # Depending on how RBAC is set and Permissions etc it is
        # possible that users won't see all media in a Category
        # but it's worth to handle this on the UI level
        # (eg through a message that says that you see only files you have permissions to see)

        self.media_count = Media.objects.filter(category=self).count()
        self.save(update_fields=["media_count"])

        # OLD logic
        # if getattr(settings, 'USE_RBAC', False) and self.is_rbac_category:
        #    self.media_count = Media.objects.filter(category=self).count()
        # else:
        #    self.media_count = Media.objects.filter(listable=True, category=self).count()

        self.save(update_fields=["media_count"])
        return True

    @property
    def thumbnail_url(self):
        """Return thumbnail for category
        prioritize processed value of listings_thumbnail
        then thumbnail
        """

        if self.thumbnail:
            return helpers.url_from_path(self.thumbnail.path)

        if self.listings_thumbnail:
            return self.listings_thumbnail

        # Optimize: Use first() directly instead of exists() + first() (saves one query)
        media = Media.objects.filter(category=self, state="public").order_by("-views").first()
        if media:
            return media.thumbnail_url

        return None

    def save(self, *args, **kwargs):
        strip_text_items = ["title", "description"]
        for item in strip_text_items:
            setattr(self, item, strip_tags(getattr(self, item, None)))
        super(Category, self).save(*args, **kwargs)


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

    title = models.CharField(max_length=100, unique=True, db_index=True)

    user = models.ForeignKey("users.User", on_delete=models.CASCADE, blank=True, null=True)

    media_count = models.IntegerField(default=0, help_text="number of media")

    listings_thumbnail = models.CharField(
        max_length=400,
        blank=True,
        null=True,
        help_text="Thumbnail to show on listings",
        db_index=True,
    )

    def __str__(self):
        return self.title

    class Meta:
        ordering = ["title"]

    def get_absolute_url(self):
        return f"{reverse('search')}?t={self.title}"

    def update_tag_media(self):
        self.media_count = Media.objects.filter(state="public", is_reviewed=True, tags=self).count()
        self.save(update_fields=["media_count"])
        return True

    def save(self, *args, **kwargs):
        self.title = helpers.get_alphanumeric_and_spaces(self.title)
        self.title = self.title[:100]
        super(Tag, self).save(*args, **kwargs)

    @property
    def thumbnail_url(self):
        if self.listings_thumbnail:
            return self.listings_thumbnail
        media = Media.objects.filter(tags=self, state="public").order_by("-views").first()
        if media:
            return media.thumbnail_url

        return None


# Import Media to avoid circular imports
from .media import Media  # noqa
