from collections import defaultdict
from django.conf import settings
from django.db.models import Q
from django.utils import timezone
from gm_types.error import ERROR

from qa.models import QuestionFavor, Answer, Question, AnswerFavor, AnswerReplyImages, AnswerReply
from utils.rpc import gen


class ProvinceService(object):

    pass


class BaseQaServices(object):
    _base_query = Q(is_online=True)

    @classmethod
    def answer_healthy(cls, answer_id):
        q = cls._base_query & Q(id=answer_id)
        try:
            answer = Answer.objects.get(q)
            return answer
        except Answer.DoesNotExist:
            return gen(ERROR.ANSWER_NOT_NLINE)

    @classmethod
    def question_healthy(cls, question_id):
        """
        :param question_id:
        :return:
        """
        q = cls._base_query & Q(id=question_id)
        try:
            question = Question.objects.get(q)
            return question
        except Question.DoesNotExist:
            return gen(ERROR.QUESTION_NOT_ONLINE)


class QaFavorServices(BaseQaServices):

    @classmethod
    def create(cls, user_id, question_id=None, answer_id=None):
        if answer_id:
            qaf, created = AnswerFavor.objects.get_or_create(
                user_id=user_id,
                answer_id=answer_id,
            )
        else:
            qaf, created = QuestionFavor.objects.get_or_create(
                user_id=user_id,
                question_id=question_id,
            )
        if not created:
            qaf.update_time = timezone.now()
            qaf.is_online = True
            qaf.save(update_fields=['is_online', 'update_time'])

        return {
            'id': qaf.id,
        }

    @classmethod
    def cancel(cls, user_id, question_id=None, answer_id=None):
        if answer_id:
            qf_id = AnswerFavor.objects.filter(
                user_id=user_id, answer_id=answer_id,
            ).update(is_online=False)
        else:
            qf_id = QuestionFavor.objects.filter(
                user_id=user_id, question_id=question_id,
            ).update(is_online=False)

        return {
            'id': qf_id,
        }

    @classmethod
    def get_message_tab_question_favor_count(cls, user_id):
        result = {
            'count': 0
        }
        question_ids = list(Question.objects.using(settings.SLAVE_DB_NAME).filter(
            user=user_id, is_online=True
        ).values_list('id', flat=True))
        if not question_ids:
            return result

        count = QuestionFavor.objects.using(settings.SLAVE_DB_NAME).filter(
            question_id__in=question_ids, is_online=True, is_read=False,
        ).count()
        result['count'] = count

        return result

    @classmethod
    def get_message_tab_answer_favor_count(cls, user_id):
        result = {
            'count': 0
        }
        answer_ids = list(Answer.objects.using(settings.SLAVE_DB_NAME).filter(
            user=user_id, is_online=True
        ).values_list('id', flat=True))
        if not answer_ids:
            return result

        count = AnswerFavor.objects.using(settings.SLAVE_DB_NAME).filter(
            answer_id__in=answer_ids, is_online=True, is_read=False,
        ).count()
        result['count'] = count

        return result

    @classmethod
    def message_favor_tab_read(cls, user_id):
        q_ids = list(Question.objects.filter(user=user_id, is_online=True).values_list('id', flat=True))
        QuestionFavor.objects.filter(question_id__in=q_ids, is_online=True, is_read=False).update(is_read=True)

        a_ids = list(Answer.objects.filter(user=user_id, is_online=True).values_list('id', flat=True))
        AnswerFavor.objects.filter(answer_id__in=a_ids, is_online=True, is_read=False).update(is_read=True)

    @classmethod
    def question_get_valid_favor(cls, ids):
        """
        获取有效的问题收藏
        :param ids:
        :return:
        """
        return QuestionFavor.objects.using(settings.SLAVE_DB_NAME).filter(id__in=ids, is_online=True)

    @classmethod
    def get_question_by_ids(cls, ids):
        """
        获取有效的问题收藏
        :param ids:
        :return:
        """
        return Question.objects.using(settings.SLAVE_DB_NAME).filter(id__in=ids)

    @classmethod
    def answer_get_valid_favor(cls, ids):
        """
        :param ids:
        :return:
        """
        return AnswerFavor.objects.using(settings.SLAVE_DB_NAME).filter(id__in=ids, is_online=True)

    @classmethod
    def get_answer_by_ids(cls, ids):
        """
        :param ids:
        :return:
        """
        return Answer.objects.using(settings.SLAVE_DB_NAME).filter(id__in=ids)

    @classmethod
    def get_favor_answer_count(cls, user_id):
        result = {
            'count': 0
        }
        if not user_id:
            return result
        result['count'] = AnswerFavor.objects.using(settings.SLAVE_DB_NAME).filter(user_id=user_id).count()

        return result

    @classmethod
    def get_favor_info_by_user_id(cls, user_id, answer_ids):
        """
        获取用户收藏的回答
        :param user_id:
        :param answer_ids:
        :return:
        """
        favored_ids = list(AnswerFavor.objects.filter(
            user_id=user_id, answer_id__in=answer_ids, is_online=True
        ).values_list('answer_id', flat=True))
        data = {}
        for answer_id in favored_ids:
            data[str(answer_id)] = True

        return data


class AnswerReplyImagesService(object):
    """
    回答评论图片
    """

    @classmethod
    def get_reply_images_by_id(cls, reply_ids):
        """
        获取评论图片
        :param reply_ids:
        :return:
        """
        if not all([reply_ids, isinstance(reply_ids, (list, tuple))]):
            return {}
        image_dict = defaultdict(list)
        reply_images = AnswerReplyImages.objects.filter(reply_id__in=reply_ids).values(
            'reply_id', 'url', 'width', 'height',
        )
        for image in reply_images:
            image_dict[image['reply_id']].append({
                'image_url': image['url'],
                'width': image['width'],
                'height': image['height'],
            })
        return image_dict


class AnswerReplyService(object):
    @classmethod
    def get_reply_count(cls, answer_id):
        return AnswerReply.objects.using(settings.SLAVE_DB_NAME).filter(
            answer_id=answer_id
        ).count()
