from django.utils import timezone

from talos.services import UserService
from .base import BaseService

from talos.models.soft_article import SoftArticleVote, SoftArticleReplyVote, SoftArticle


class SoftArticleVoteService(BaseService):

    model = SoftArticleVote

    @classmethod
    def set_read_by_user_id(cls, user_id):
        softarticle_ids = SoftArticle.objects.filter(is_online=True, user_id=user_id).values_list('id', flat=True)

        cls.model.objects.filter(softarticle_id__in=softarticle_ids).update(
            is_read=True,
            update_time=timezone.now()
        )

    @classmethod
    def create(cls, user_id, softarticle_id):
        """创建点赞。"""

        tv, created = cls.model.objects.get_or_create(
            softarticle_id=softarticle_id,
            user_id=user_id,
        )
        if not tv.is_online:
            tv.is_online = True
            tv.is_read = False
            tv.save()

        return tv

    @classmethod
    def cancel(cls, softarticle_id, user_id):
        """
        新帖子取消点赞
        :return:
        """
        tv, _ = cls.model.objects.update_or_create(
            user_id=user_id, softarticle_id=softarticle_id,
            defaults={"is_online": False, "update_time": timezone.now()}
        )

        return tv

    @classmethod
    def unread_count(cls, softarticle_id):
        """
        点赞未读数
        :return:
        """
        count = cls.model.objects.filter(softarticle_id=softarticle_id, is_read=False).count()
        return count

    @classmethod
    def get_softarticle_voted_info_for_user(cls, softarticle_ids, user_id):
        """
        获取用户对帖子已点赞的数据
        :param softarticle_ids:
        :param user_id:
        :return:
        """
        result = dict()
        if not softarticle_ids or not user_id:
            return result

        tvs = list(cls.model.objects.filter(
            softarticle_id__in=softarticle_ids,
            user_id=user_id,
            is_online=True
        ).values_list("softarticle_id", flat=True))
        if not tvs:
            return result

        result = {tv: True for tv in tvs}
        return result


class SoftArticleReplyVoteService(BaseService):

    model = SoftArticleReplyVote

    @classmethod
    def set_read_by_user_id(cls, user_id):

        sortarticle_ids = SoftArticle.objects.filter(is_online=True, user_id=user_id).values_list('id', flat=True)

        cls.model.objects.filter(sortarticle_id__in=sortarticle_ids).update(
            is_read=True,
            update_time=timezone.now()
        )

    @classmethod
    def create(cls, user_id, reply):
        """创建点赞。"""
        try:
            trv = cls.model.objects.get(user_id=user_id, softarticle_id=reply.softarticle_id, reply_id=reply.id)
        except SoftArticleReplyVote.DoesNotExist:
            trv = cls.model.objects.create(user_id=user_id, softarticle_id=reply.softarticle_id, reply_id=reply.id)

        if not trv.is_online:
            trv.is_online = True
            trv.save()

        reply_author = UserService.get_user_by_user_id(user_id=reply.user_id)
        reply_author.incr_vote_count()

        return reply, trv

    @classmethod
    def cancel(cls, user_id, reply):
        """
        帖子回复取消点赞
        :param reply:
        :param user_id:
        :return:
        """

        cls.model.objects.filter(user_id=user_id, reply_id=reply.id).update(
            is_online=False, update_time=timezone.now())

        author = UserService.get_user_by_user_id(reply.user_id)
        author.decr_vote_count()

    @classmethod
    def unread_count(cls, softarticle_id):
        """
        回复点赞未读数
        :param softarticle_id:
        :return:
        """
        count = cls.model.objects.filter(softarticle_id=softarticle_id, is_read=False).count()
        return count

    @classmethod
    def get_vote_status(cls, user_id, softarticle_id, reply_ids):
        if not user_id:
            return []

        replied_ids = cls.model.objects.filter(softarticle_id=softarticle_id, user_id=user_id,
                                               reply_id__in=reply_ids, is_online=True)\
                                       .values_list('reply_id', flat=True)

        return list(replied_ids)