import datetime
import random

from django.conf import settings
from gm_protocol import GmProtocol
from gm_rpcd.internals.exceptions import RPCDFaultException
from gm_types.gaia import LIST_TRACTATE_FROM
from gm_types.push import AUTOMATED_PUSH, PUSH_INFO_TYPE
from gm_types.mimas import COMMUNITY_CONTENT_TYPE, NOTICATION_LIST_CATEGORY

from communal.services.fake.fake_service import FakeService
from qa.libs import _get_content_text
from qa.models import AnswerTagV3, AnswerReply, Answer, AnswerVote
from qa.service import QaFavorServices
from qa.services import QualityQuestionService
from qa.tasks import comment_push, write_unread_data, questioning_push
from talos.cache.base import vote_cache
from talos.logger import info_logger
from talos.models.diary import DiaryTagV3
from talos.models.topic import ProblemTagV3, TopicVote, Problem, TopicReply
from talos.models.tractate import TractateTagV3, TractateVote
from talos.services import UserService, UserConvertService
from talos.services.tractate import TractateService, TractateVoteService, TractateReplyService
from talos.tasks import push_diary_reply_message, get_sleep_user
from talos.tools.replies_tool import ReplyTool
from talos.tools.vote_tool import VoteTool
from talos.cache.base import reply_cache as reply_msg_cache
from talos.tasks.tractate import reply_push
from utils.protocol import gm_protocol
from utils.push import vote_push
from communal.tasks import intelligent_push_task


def get_paas_sleep_users(count):
    user_ids = get_sleep_user(count)
    return user_ids


class FakeBehaviorService(object):
    """
    内容灌水的各种行为 整理在这里，减少跟之前逻辑耦合、避免后期逻辑变更不好修改
    """
    @classmethod
    def valid_time_limit(cls):
        date_now = datetime.datetime.now()
        if not 9 <= date_now.hour <= 22:
            return False
        return True

    @classmethod
    def tractate_push(cls, tractate, author, user, push_type, alert="{}赞了你的帖子{}", jump_to_vote_list=False):
        """

        :param tractate:
        :param author:
        :param user:
        :param push_type:
        :param alert:
        :param jump_to_vote_list: 是否跳转到消息页的赞列表 True/False
        :return:
        """

        date_now = datetime.datetime.now()
        if not 9 <= date_now.hour <= 22:
            return
        push_url = GmProtocol().get_tractate_detail(
            tractate_id=tractate.id,
            tractate_detail_from=LIST_TRACTATE_FROM.NOTICE_VOTE
        )

        if jump_to_vote_list:
            push_url = GmProtocol().vote_or_favor_list(
                segment_index=NOTICATION_LIST_CATEGORY.VOTE,
                new_vote=True,
            )

        alert = u'有1位朋友给你点了赞，快来看看吧>>'
        intelligent_push_task.delay(
            content_id=tractate.id,
            user_ids=[tractate.user_id],
            push_type=AUTOMATED_PUSH.TRACTATE_GET_VOTED,
            platform=None,
            extra={
                'type': PUSH_INFO_TYPE.GM_PROTOCOL,
                'pushUrl': push_url,
                'push_url': push_url,
            },
            alert=alert,
            others={
                "title": "@{} 给你点了赞".format(user.nickname),
                "alert": alert,
            },
            labels={},
        )

    @classmethod
    def tractate_vote(cls, tractate_id, user_id, author_id, jump_to_vote_list=False):
        """
        :param tractate_id:
        :param user_id:         点赞的马甲号
        :return:
        """
        info_logger.info('begin tractate:{} fake vote'.format(tractate_id))
        try:
            tractate = TractateService.healthy(tractate_id)
        except RPCDFaultException:
            info_logger.info('帖子:{}已经被下线，不需要灌水'.format(tractate_id))
            return
        if settings.DEBUG:
            user_ids = get_paas_sleep_users(1)
            if not user_ids:
                return
            user_id = user_ids and user_ids[0]
        tv, created = TractateVote.objects.get_or_create(
            tractate_id=tractate.id,
            user_id=user_id,
            is_fake=True,
        )
        if not created:
            return

        # 对作者添加点赞数
        users = UserService.get_users_by_user_ids([tractate.user_id, user_id])
        author = users.get(tractate.user_id, {})
        user = users.get(user_id, {})
        if author:
            author.incr_vote_count()

        TractateService.inc_tractate_vote(tractate)

        vote_tool = VoteTool(redis_c=vote_cache, user_id=tractate.user_id, new_version=True)
        vote_tool.receive_tractate_vote(tv.id)

        cls.tractate_push(tractate, author, user, push_type=AUTOMATED_PUSH.TRACTATE_GET_VOTED,
                          alert='{}赞了你的帖子{}', jump_to_vote_list=jump_to_vote_list)

    @classmethod
    def tractate_reply(cls, tractate_id, user_id, author_id):
        info_logger.info('begin tractate:{} fake reply'.format(tractate_id))
        try:
            tractate = TractateService.healthy(tractate_id)
        except RPCDFaultException:
            info_logger.info('帖子:{}已经被下线，不需要灌水'.format(tractate_id))
            return
        tractate_tag_ids = list(TractateTagV3.objects.using(settings.SLAVE_DB_NAME).filter(
            tractate_id=tractate_id).values_list('tag_v3_id', flat=True))
        content = FakeService.get_comment_by_tag_ids(
            tag_ids=tractate_tag_ids, content_id=tractate_id, content_type=COMMUNITY_CONTENT_TYPE.TRACTATE)
        if not content:
            info_logger.info('tractate:{}can not get reply，finish'.format(tractate_id))
            return
        if settings.DEBUG:
            user_ids = get_paas_sleep_users(1)
            if not user_ids:
                return
            user_id = user_ids and user_ids[0]
        reply = TractateReplyService.create(
            content=content, user_id=user_id,
            tractate_id=tractate_id, extra={
                "is_fake": True,
            }
        )

        rt = ReplyTool(reply_msg_cache, tractate.user_id)
        rt.receive_tractate_reply(reply.id)

        TractateService.incr_tractate_reply(tractate=tractate)

        reply_push.delay(user_id=user_id, tractate_id=tractate_id, reply_id=reply.id, content=content)

    @classmethod
    def answer_reply(cls, answer_id, user_id, author_id):
        info_logger.info('begin answer:{} fake reply'.format(answer_id))

        answer_tag3_ids = list(AnswerTagV3.objects.using(settings.SLAVE_DB_NAME).filter(
            answer_id=answer_id).values_list('tag_v3_id', flat=True))
        content = FakeService.get_comment_by_tag_ids(
            tag_ids=answer_tag3_ids, content_id=answer_id, content_type=COMMUNITY_CONTENT_TYPE.ANSWER)
        if not content:
            info_logger.info('answer:{}can not get reply，finish'.format(answer_id))
            return
        if settings.DEBUG:
            user_ids = get_paas_sleep_users(1)
            if not user_ids:
                return
            user_id = user_ids and user_ids[0]
        data = {
            'user': user_id,
            'content': content,
            'answer_id': answer_id,
            'commented_reply': None,
            'is_fake': True,
        }
        answer_reply = AnswerReply.objects.create(**data)
        # push
        user = UserService.get_user_by_user_id(user_id)
        if not user:
            return
        comment_push(
            answer_id=answer_id,
            comment_id=answer_reply.id,
            author_name=user.nickname,
            content=content,
            user_id=author_id,
        )

    @classmethod
    def answer_vote(cls, answer_id, user_id, author_id, jump_to_vote_list=False):
        """

        :param answer_id:
        :param user_id:
        :param author_id:
        :param jump_to_vote_list: 是否跳转到消息页的赞列表 True/False
        :return:
        """
        info_logger.info('begin answer:{} fake vote'.format(answer_id))

        if settings.DEBUG:
            user_ids = get_paas_sleep_users(1)
            if not user_ids:
                return
            user_id = user_ids and user_ids[0]
        data = {'user': user_id, 'answer_id': answer_id, 'is_fake': True}
        vote, created = AnswerVote.objects.get_or_create(**data)
        if not created:
            return

        vt_v1 = VoteTool(vote_cache, user_id, new_version=True)
        vt_v1.receive_answer_vote(vote.id)

        user = UserService.get_user_by_user_id(user_id)
        push_url = GmProtocol().get_answer_list(answer=answer_id)
        if jump_to_vote_list:
            push_url = GmProtocol().vote_or_favor_list(
                segment_index=NOTICATION_LIST_CATEGORY.VOTE,
                new_vote=True,
            )
        alert = u'有1位朋友给你点了赞，快来看看吧>>'
        intelligent_push_task.delay(
            content_id=answer_id,
            user_ids=[author_id],
            push_type=AUTOMATED_PUSH.ANSWER_GET_VOTE,
            platform=None,
            extra={
                'type': PUSH_INFO_TYPE.GM_PROTOCOL,
                'pushUrl': push_url,
                'push_url': push_url,
            },
            alert=alert,
            others={
                "title": "@{} 给你点了赞".format(user.nickname),
                "alert": alert,
            },
            labels={},
        )

    @classmethod
    def answer_quality(cls, answer_id, user_id, author_id):
        info_logger.info('begin answer:{} fake quality question'.format(answer_id))

        answer_tag3_ids = list(AnswerTagV3.objects.using(settings.SLAVE_DB_NAME).filter(
            answer_id=answer_id).values_list('tag_v3_id', flat=True))
        # 1、先获取追问问题
        tag_question_ids_map = QualityQuestionService.list_question_by_tags(answer_tag3_ids)

        # 取ID最小有数据标签就可以了
        question_ids = []
        for tag_id in sorted(answer_tag3_ids):
            if tag_id in tag_question_ids_map:
                question_ids = tag_question_ids_map[tag_id]
                break

        questions_dict = QualityQuestionService.list_question_by_ids(question_ids)
        if questions_dict:
            questions_info = [questions_dict[question_id] for question_id in question_ids if
                              question_id in questions_dict]
        else:
            questions_info = QualityQuestionService.list_common_question()
        if not questions_info:
            info_logger.info('answer:{}can not get quality question，finish'.format(answer_id))
            return
        quality_question = random.choice(questions_info)
        question = QualityQuestionService.question_check_or_get(quality_question['id'])
        if settings.DEBUG:
            user_ids = get_paas_sleep_users(1)
            if not user_ids:
                return
            user_id = user_ids and user_ids[0]
        try:
            question_info = QualityQuestionService.questioning(answer_id, question, user_id)
        except:
            info_logger.info('answer_id:{},user:{} already create quality question'.format(user_id, answer_id))
            return
        # 追问成功，默认收藏该回答
        QaFavorServices.create(user_id=user_id, answer_id=answer_id)

        # fill user info
        user_info = UserConvertService.get_user_info_by_user_id(question_info["user"]["id"])
        question_info["user"].update(user_info)

        write_unread_data.delay(question_info['id'], answer_id, _type='ask_question')
        questioning_push.delay(user_id, answer_id, question_info['id'], question.title)

    @classmethod
    def topic_reply(cls, problem_id, user_id, author_id):
        info_logger.info('begin topic:{} fake reply'.format(problem_id))

        tag3_ids = list(ProblemTagV3.objects.using(settings.SLAVE_DB_NAME).filter(
            problem_id=problem_id).values_list('tag_v3_id', flat=True))
        # 日记帖没有新标签用对应日记本的新标签
        if not tag3_ids:
            try:
                problem = Problem.objects.get(id=problem_id)
            except Problem.DoesNotExist:
                info_logger.info('topic:{} does not exists，finish'.format(problem_id))
                return
            if not problem.diary_id:
                info_logger.info('topic:{} does not related diary，finish'.format(problem_id))
                return
            tag3_ids = list(DiaryTagV3.objects.using(settings.SLAVE_DB_NAME).filter(
                diary_id=problem.diary_id).values_list('tag_v3_id', flat=True))
        content = FakeService.get_comment_by_tag_ids(
            tag_ids=tag3_ids, content_id=problem_id, content_type=COMMUNITY_CONTENT_TYPE.TOPIC)
        if not content:
            info_logger.info('topic:{} can not get reply，finish'.format(problem_id))
            return
        if settings.DEBUG:
            user_ids = get_paas_sleep_users(1)
            if not user_ids:
                return
            user_id = user_ids and user_ids[0]
        user = UserService.get_user_by_user_id(user_id)
        data = {
            'problem_id': problem_id,
            'user_id': user.id,
            'content': content,
            'is_fake': True,
        }
        topic_reply = TopicReply.objects.create(**data)
        push_diary_reply_message(
            user_id=user_id, content=content, reply_id=None, topic_id=problem_id,
            replied_reply_user_id=0, diary_user_id=author_id, topic_user_id=author_id
        )

    @classmethod
    def topic_vote(cls, problem_id, user_id, author_id, jump_to_vote_list=False):
        info_logger.info('begin topic:{} fake reply'.format(problem_id))

        problem = Problem.objects.using(settings.SLAVE_DB_NAME).get(id=problem_id)
        if settings.DEBUG:
            user_ids = get_paas_sleep_users(1)
            if not user_ids:
                return
            user_id = user_ids and user_ids[0]
        t, created = TopicVote.objects.get_or_create(
            user_id=user_id, topic_id=problem_id, topic_author_id=author_id, is_fake=True)
        if not created:
            return

        # 对作者增加点赞数
        users = UserService.get_users_by_user_ids([problem.user_id, user_id])
        topic_author = users.get(problem.user_id, {})
        if topic_author:
            topic_author.incr_vote_count()
        user = users.get(user_id, {})

        if problem.diary_id:
            alert = u'{user_name}刚刚赞了你的《{diary_title}》，比心~'.format(
                user_name=user.nickname if user else '更美用户', diary_title=problem.diary.title)
            push_url = GmProtocol().get_topic_detail(id=problem.id)
            if jump_to_vote_list:
                push_url = GmProtocol().vote_or_favor_list(
                    segment_index=NOTICATION_LIST_CATEGORY.VOTE,
                    new_vote=True,
                )
            vote_push(user_id=problem.user_id, alert=alert, push_url=push_url,
                      push_type=AUTOMATED_PUSH.DIARY_POST_RECEIVED_PRAISE)
