# 用户关注和收藏功能模型
# 实现用户间的关注关系和文章收藏功能

from django.conf import settings
from django.db import models
from django.utils.timezone import now
from django.utils.translation import gettext_lazy as _

from blog.models import Article


class UserFollow(models.Model):
    """
    用户关注模型
    记录用户之间的关注关系
    """
    # 关注者（谁关注了别人）
    follower = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        verbose_name='关注者',
        on_delete=models.CASCADE,
        related_name='following'
    )

    # 被关注者（被谁关注）
    following = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        verbose_name='被关注者',
        on_delete=models.CASCADE,
        related_name='followers'
    )

    # 关注时间
    creation_time = models.DateTimeField('创建时间', default=now, db_index=True)

    class Meta:
        ordering = ['-creation_time']
        verbose_name = '用户关注'
        verbose_name_plural = '用户关注'
        unique_together = [['follower', 'following']]
        indexes = [
            models.Index(fields=['follower', '-creation_time'], name='follow_follower_time_idx'),
            models.Index(fields=['following', '-creation_time'], name='follow_following_time_idx'),
        ]

    def __str__(self):
        return f"{self.follower.username} -> {self.following.username}"

    def clean(self):
        """验证：不能关注自己"""
        from django.core.exceptions import ValidationError
        if self.follower == self.following:
            raise ValidationError(_('Cannot follow yourself'))

    @classmethod
    def is_following(cls, follower, following):
        """
        检查是否已关注

        Args:
            follower: 关注者用户对象
            following: 被关注者用户对象

        Returns:
            bool: 是否已关注
        """
        return cls.objects.filter(follower=follower, following=following).exists()

    @classmethod
    def follow(cls, follower, following):
        """
        关注用户

        Args:
            follower: 关注者用户对象
            following: 被关注者用户对象

        Returns:
            UserFollow 实例或 None
        """
        if follower == following:
            return None

        follow, created = cls.objects.get_or_create(
            follower=follower,
            following=following
        )
        return follow if created else None

    @classmethod
    def unfollow(cls, follower, following):
        """
        取消关注

        Args:
            follower: 关注者用户对象
            following: 被关注者用户对象

        Returns:
            bool: 是否成功取消关注
        """
        deleted_count, _ = cls.objects.filter(
            follower=follower,
            following=following
        ).delete()
        return deleted_count > 0

    @classmethod
    def get_following_list(cls, user, limit=None):
        """
        获取用户关注的人列表

        Args:
            user: 用户对象
            limit: 返回数量限制

        Returns:
            QuerySet: 关注的用户列表
        """
        queryset = cls.objects.filter(follower=user).select_related('following')
        if limit:
            queryset = queryset[:limit]
        return [f.following for f in queryset]

    @classmethod
    def get_followers_list(cls, user, limit=None):
        """
        获取用户的粉丝列表

        Args:
            user: 用户对象
            limit: 返回数量限制

        Returns:
            QuerySet: 粉丝用户列表
        """
        queryset = cls.objects.filter(following=user).select_related('follower')
        if limit:
            queryset = queryset[:limit]
        return [f.follower for f in queryset]

    @classmethod
    def get_following_count(cls, user):
        """获取关注数量"""
        return cls.objects.filter(follower=user).count()

    @classmethod
    def get_followers_count(cls, user):
        """获取粉丝数量"""
        return cls.objects.filter(following=user).count()


class ArticleFavorite(models.Model):
    """
    文章收藏模型
    记录用户收藏的文章
    """
    # 用户
    user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        verbose_name='用户',
        on_delete=models.CASCADE,
        related_name='favorites'
    )

    # 文章
    article = models.ForeignKey(
        Article,
        verbose_name='文章',
        on_delete=models.CASCADE,
        related_name='favorited_by'
    )

    # 收藏时间
    creation_time = models.DateTimeField('创建时间', default=now, db_index=True)

    # 收藏备注（可选）
    note = models.CharField('备注', max_length=200, blank=True, default='')

    class Meta:
        ordering = ['-creation_time']
        verbose_name = '文章收藏'
        verbose_name_plural = '文章收藏'
        unique_together = [['user', 'article']]
        indexes = [
            models.Index(fields=['user', '-creation_time'], name='favorite_user_time_idx'),
            models.Index(fields=['article', '-creation_time'], name='favorite_article_time_idx'),
        ]

    def __str__(self):
        return f"{self.user.username} -> {self.article.title}"

    @classmethod
    def is_favorited(cls, user, article):
        """
        检查是否已收藏

        Args:
            user: 用户对象
            article: 文章对象

        Returns:
            bool: 是否已收藏
        """
        return cls.objects.filter(user=user, article=article).exists()

    @classmethod
    def add_favorite(cls, user, article, note=''):
        """
        收藏文章

        Args:
            user: 用户对象
            article: 文章对象
            note: 收藏备注

        Returns:
            ArticleFavorite 实例或 None
        """
        favorite, created = cls.objects.get_or_create(
            user=user,
            article=article,
            defaults={'note': note}
        )
        return favorite if created else None

    @classmethod
    def remove_favorite(cls, user, article):
        """
        取消收藏

        Args:
            user: 用户对象
            article: 文章对象

        Returns:
            bool: 是否成功取消收藏
        """
        deleted_count, _ = cls.objects.filter(
            user=user,
            article=article
        ).delete()
        return deleted_count > 0

    @classmethod
    def get_user_favorites(cls, user, limit=None):
        """
        获取用户的收藏列表

        Args:
            user: 用户对象
            limit: 返回数量限制

        Returns:
            QuerySet: 收藏的文章列表
        """
        queryset = cls.objects.filter(user=user).select_related('article', 'article__author', 'article__category')
        if limit:
            queryset = queryset[:limit]
        return queryset

    @classmethod
    def get_favorite_count(cls, user):
        """获取用户收藏数量"""
        return cls.objects.filter(user=user).count()

    @classmethod
    def get_article_favorite_count(cls, article):
        """获取文章被收藏次数"""
        return cls.objects.filter(article=article).count()


class ArticleLike(models.Model):
    """
    文章点赞模型
    记录用户对文章的点赞
    """
    # 用户
    user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        verbose_name='用户',
        on_delete=models.CASCADE,
        related_name='likes'
    )

    # 文章
    article = models.ForeignKey(
        Article,
        verbose_name='文章',
        on_delete=models.CASCADE,
        related_name='liked_by'
    )

    # 点赞时间
    creation_time = models.DateTimeField('创建时间', default=now, db_index=True)

    class Meta:
        ordering = ['-creation_time']
        verbose_name = '文章点赞'
        verbose_name_plural = '文章点赞'
        unique_together = [['user', 'article']]
        indexes = [
            models.Index(fields=['user', '-creation_time'], name='like_user_time_idx'),
            models.Index(fields=['article', '-creation_time'], name='like_article_time_idx'),
        ]

    def __str__(self):
        return f"{self.user.username} 👍 {self.article.title}"

    @classmethod
    def is_liked(cls, user, article):
        """
        检查是否已点赞

        Args:
            user: 用户对象
            article: 文章对象

        Returns:
            bool: 是否已点赞
        """
        return cls.objects.filter(user=user, article=article).exists()

    @classmethod
    def add_like(cls, user, article):
        """
        点赞文章

        Args:
            user: 用户对象
            article: 文章对象

        Returns:
            ArticleLike 实例或 None
        """
        like, created = cls.objects.get_or_create(
            user=user,
            article=article
        )
        return like if created else None

    @classmethod
    def remove_like(cls, user, article):
        """
        取消点赞

        Args:
            user: 用户对象
            article: 文章对象

        Returns:
            bool: 是否成功取消点赞
        """
        deleted_count, _ = cls.objects.filter(
            user=user,
            article=article
        ).delete()
        return deleted_count > 0

    @classmethod
    def get_article_like_count(cls, article):
        """
        获取文章点赞数

        Args:
            article: 文章对象

        Returns:
            int: 点赞数
        """
        return cls.objects.filter(article=article).count()

    @classmethod
    def get_user_like_count(cls, user):
        """
        获取用户点赞数

        Args:
            user: 用户对象

        Returns:
            int: 用户点赞的文章数量
        """
        return cls.objects.filter(user=user).count()

    @classmethod
    def get_user_likes(cls, user, limit=None):
        """
        获取用户点赞的文章列表

        Args:
            user: 用户对象
            limit: 返回数量限制

        Returns:
            QuerySet: 点赞的文章列表
        """
        queryset = cls.objects.filter(user=user).select_related('article', 'article__author', 'article__category')
        if limit:
            queryset = queryset[:limit]
        return queryset
