#!/usr/bin/env python
# -*- coding: utf-8 -*-
'''
__title__ = ''
__author__ = 'xierong@gmei.com'
__mtime__ = '17/12/22'
'''
from __future__ import unicode_literals, absolute_import, print_function

import datetime
import json
import random
import re
from urllib.request import urlopen
from datetime import timedelta

from bs4 import BeautifulSoup
from celery import shared_task
from django.conf import settings
from django.db.models import Count
from django.utils import timezone

from gm_types.gaia import TOPIC_TYPE
from gm_types.push import PUSH_INFO_TYPE, AUTOMATED_PUSH
from gm_protocol import GmProtocol
from gm_upload import upload, IMG_TYPE
from gm_upload.utils.image_utils import Picture

from utils.rpc import rpc_client, logging_exception
from utils.push import push_task_to_user_multi, special_push_limit
from utils.wx import WxTkApi

from qa.models.answer import Question, Answer, QuestionImage, AnswerImage, QuestionTag, AnswerReply

from talos.cache.base import wechat_cache
from talos.services import UserService
from talos.models.topic import (
    Problem,
    ProblemTag,
)
from talos.models.doctor import DoctorMessageList
from talos.models.topic import TopicVote
from talos.models.topic import WechatMaterial

from .vote import fake_vote


# @shared_task
# def hot_in_24hrs():
#     query = TopicVote.objects.filter(
#         vote_time__range=(timezone.now() - timedelta(hours=24), timezone.now())
#     )
#     query = query.values('topic')
#     result = query.annotate(vote_num=Count('topic')).order_by('-vote_num')
#
#     data = []
#
#     user_ids = set()
#     start = 0
#     count = 20
#
#     while True:
#         result = result[start:start + count]
#         if not result:
#             break
#
#         start += count
#         topic_ids = [d['topic'] for d in result]
#         topics = Problem.objects.filter(
#             pk__in=topic_ids, is_online=True, is_sink=False)
#
#         for t in topics:
#             if t.user.id in user_ids:
#                 continue
#             user_ids.add(t.user.id)
#             data.append(t.id)
#
#             if len(user_ids) >= count:
#                 break
#
#     # save data in redis
#     hot_in_24hrs_cache.set('topics', json.dumps(data))
#     return data


@shared_task
def push_diary_update_to_follow(diary_id, user_id, diary_title=None):
    """
    用户发日记贴 推送给粉丝
    :param diary_id:
    :param user_id:
    :return:
    """
    if str(user_id) == '22':
        return

    try:
        user_name = UserService.get_user_by_user_id(user_id).nickname
    except:
        logging_exception()
        return

    if user_name.startswith(u'更美用户'):
        user_name = u'匿名美人'

    try:
        user_ids = rpc_client['api/user/get_all_fans'](user_id=user_id).unwrap()
        #user_ids = [uid for uid in user_ids if special_push_limit(uid, "user_released_diary", user_id)]
    except:
        logging_exception()
        return

    kwargs = {
        "user_ids": user_ids,
        "platform": ['android', 'iPhone'],
        "alert": u'嗨，你关注的 @{user_name}刚刚在《{diary_title}》中更新了一篇日记。快去看看 ta 变美了多少~'.format(user_name=user_name, diary_title=diary_title),
        "extra": {
            'type': PUSH_INFO_TYPE.GM_PROTOCOL,
            'msgType': 4,
            'pushUrl': GmProtocol().get_diary_detail(id=diary_id),
            'push_url': GmProtocol().get_diary_detail(id=diary_id),
        },
        "push_type": AUTOMATED_PUSH.FOLLOWED_USER_POSTED_JOURNAL_POSTS,
    }
    push_task_to_user_multi(**kwargs)


@shared_task
def fake_vote_to_topic():
    now = datetime.datetime.now()
    time_delta = datetime.timedelta(days=30)
    start_date = now.date() - time_delta

    topics = Problem.objects.using(settings.SLAVE_DB_NAME).filter(last_modified__gte=start_date, votes__isnull=True).values_list('id', flat=True)
    count = topics.count()
    topics = list(topics)
    topics = Problem.objects.filter(id__in=topics)
    topics_index = random.sample(range(0, count), min(20, count))

    for index in topics_index:
        times = random.randint(1, 3)
        fake_vote(times, topics[index].id)


@shared_task
def move_topic_to_answer():  # 非日记帖 同步成问答
    num = 100
    question_obj = Question.objects.filter(problem_id__isnull=False).order_by('-problem_id').first()
    if question_obj:
        max_problem_id = question_obj.problem_id
        all_problem = Problem.objects.filter(is_online=True, topic_type__in=[TOPIC_TYPE.ASK, TOPIC_TYPE.TOPIC],
                                             id__gt=max_problem_id)
        problems, index = all_problem[0:num], 0
        while problems:
            for problem in problems:
                convert_question_topic(problem)
            index += 1
            problems = all_problem[index * num: (index + 1) * num]


def convert_question_topic(problem):
    try:
        problem.stream
        return
    except:
        pass
    try:
        content = problem.ask + problem.answer
        title = re.split("\?|？", content)[0]
        q = Question.objects.create(user_id=problem.user_id, problem_id=problem.id,
                                    title=title[0:100], content=content,
                                    create_time=problem.created_time, update_time=problem.created_time)

        for tag in problem.tags.all():
            QuestionTag(question=q, tag=tag.id).save()

        for image in problem.images.all():
            QuestionImage.objects.create(question=q, image_url=image.image_url)
        print('finish problem id: ' + str(problem.id))
        convert_answer_topic_reply(question=q, problem=problem)

    except Exception as e:
        print(e)
        print('error: problem id: ' + str(problem.id))


def convert_answer_topic_reply(question, problem):
    replys = problem.topicreply_set.filter(is_online=True, commented_reply__isnull=True)
    for reply in replys:
        try:
            answer = Answer.objects.create(user_id=reply.user_id,
                                           topicreply_id=reply.id,
                                           question=question,
                                           content=reply.content,
                                           like_num=reply.like_num,
                                           create_time=reply.reply_date,
                                           update_time=reply.reply_date)
            for image in reply.images.all():
                AnswerImage.objects.create(image_url=image.image_url, answer=answer)

            print('finish reply id: ' + str(reply.id))

            convert_answer_reply_topic_reply(answer, reply)
        except Exception as e:
            print(e)
            print('error: reply id: ' + reply.id)


def convert_answer_reply_topic_reply(answer, topicreply):
    topicreplys = topicreply.comments.filter(is_online=True)
    for reply in topicreplys:
        try:
            answer_reply = AnswerReply.objects.create(content=reply.content,
                                                      user_id=reply.user_id,
                                                      answer=answer,
                                                      create_time=reply.reply_date,
                                                      update_time=reply.reply_date,
                                                      topicreply_id=reply.id,
                                                      like_num=reply.like_num)
            print('finish reply id: ' + str(reply.id))

        except Exception as e:
            print(e)
            print('error: reply id ' + reply.id)


@shared_task
def get_wechat_pgc(offset=0, size=10, run_all=False):
    wx_client = WxTkApi()
    access_token = wx_client.get_access_token()
    wechat_result = wx_client.get_material_list(
        access_token=access_token, offset=offset, count=size
    )
    material_list = json.loads(wechat_result)
    create_wechat_ugc(material_list)
    # get the total count
    total_count = material_list['total_count']
    if not run_all:
        total_count = offset + 20

    while offset < total_count:
        offset += size
        access_token = wx_client.get_access_token()
        wechat_result = wx_client.get_material_list(
            access_token=access_token, offset=offset, count=size)
        material_list = json.loads(wechat_result)
        if not material_list:
            break
        create_wechat_ugc(material_list)


def create_wechat_ugc(material_list):
    if not material_list:
        return

    user = UserService.get_user_by_user_id(settings.WX_USER_ID)
    for material in material_list['item']:
        created_time = datetime.datetime.fromtimestamp(material['update_time'])
        i = 0
        media_id = material['media_id']
        for item in material['content']['news_item']:
            # checkout if material already downloaded
            material_gmei, result = WechatMaterial.objects.get_or_create(material_id=media_id, number=i)
            if (result is False
                    and material_gmei.topic_id
                    and material_gmei.update_time == created_time):
                continue

            item_content = str(item['content'], "utf-8") if type(item["content"]) == bytes else item["content"]  # 数据类型
            material_gmei.thumb_media_id = item['thumb_media_id']
            material_gmei.thumb_url = item['thumb_url']
            material_gmei.show_cover_pic = item['show_cover_pic']
            material_gmei.author = item['author']
            material_gmei.digest = item['digest']
            material_gmei.content = item_content
            material_gmei.url = item['url']
            material_gmei.content_source_url = item['content_source_url']
            material_gmei.update_time = created_time
            material_gmei.title = item['title']

            title = item['title']
            content = u"<html><body>{content}</body></html>".format(content=item_content)
            soup = BeautifulSoup(content, 'lxml')
            images = soup.find_all("img")
            problem, result = Problem.objects.get_or_create(
                user_id=user.id, ask=title,
                topic_type=TOPIC_TYPE.WEIXIN_NUM, audit_status=False,
                is_online=False
            )

            try:
                for image in images:
                    url = image.attrs['data-src']
                    if not url:
                        continue

                    # if src has value then continue
                    if image.attrs.get('src', ''):
                        continue

                    if not url:
                        continue

                    data = urlopen(url).read()
                    image_url = upload(image_file=data, img_type=IMG_TYPE.NOWATERMARK)
                    image.attrs['src'] = Picture.get_w_path(image_url)
            except:
                logging_exception()
                # push error material id into the rerun queue
                redis_key = "wechat_rerun_queue"
                wechat_cache.lpush(redis_key, problem.id)

            html_content = str(soup.body).replace("</body>", "").replace("<body>", "")
            problem.answer = html_content
            problem.created_time = created_time
            problem.save()

            material_gmei.topic_id = problem.id
            material_gmei.save()
            i += 1


@shared_task
def rerun_pgc():
    redis_key = "wechat_rerun_queue"
    limit = 10
    problem_ids = []
    while True:
        for i in range(0, limit):
            problem_id = wechat_cache.rpop(redis_key)
            if problem_id:
                problem_ids.append(problem_id)
        if not problem_ids:
            break

        problems = Problem.objects.filter(id__in=problem_ids)
        for problem in problems:
            rerun(problem)


def rerun(problem):
    if not isinstance(problem, Problem):
        return
    content = u"<html><body>{content}</body></html>".format(content=problem.answer)
    soup = BeautifulSoup(content, 'lxml')
    images = soup.find_all("img")
    try:
        for image in images:
            if image.attrs.get('src'):
                continue

            url = image.attrs['data-src']
            if not url:
                continue

            data = urlopen(url).read()
            image_url = upload(image_file=data, img_type=IMG_TYPE.NOWATERMARK)
            image.attrs['src'] = Picture.get_w_path(image_url)

        html_content = str(soup.body).replace("</body>", "").replace("<body>", "")
        problem.answer = html_content
        problem.save()
    except:
        logging_exception()
        # push error material id into the rerun queue
        redis_key = "wechat_rerun_queue"
        wechat_cache.lpush(redis_key, problem.id)


@shared_task
def async_diary_change_tags_to_topic(topic_ids, add_tags, del_tags):
    """
    将日记本变动的标签，同步到帖子上
    :param topic_ids:
    :param add_tags:
    :param del_tags:
    :return:
    """
    # 更新需要创建的标签
    exist_topic_tag_group = list(
        ProblemTag.objects.filter(problem_id__in=topic_ids, tag_id__in=add_tags).values_list("problem_id", "tag_id"))

    topic_tag_group = [(topic_id, tag_id) for tag_id in add_tags for topic_id in topic_ids]
    can_create_list = list(filter(lambda x: x not in exist_topic_tag_group, topic_tag_group))
    ProblemTag.objects.bulk_create(
        [ProblemTag(problem_id=topic_id, tag_id=tag_id) for topic_id, tag_id in can_create_list])

    # 删掉需要剔除的标签
    ProblemTag.objects.filter(problem_id__in=topic_ids, tag_id__in=del_tags).delete()


@shared_task
def add_doctor_topic(topic_ids, user_id):
    """添加医生关联的日记贴"""

    topics = Problem.objects.filter(id__in=topic_ids, is_online=True).select_related("diary")
    if not topics:
        return

    service_id = topics[0].diary.service_id
    if not service_id:
        return

    try:
        doctors = rpc_client["api/doctor/list_by_service_ids"](service_ids=[service_id]).unwrap()
        doctor_id = doctors.get(str(service_id), {}).get("id")
    except:
        logging_exception()
        return

    if not doctor_id:
        return

    messages = []
    for topic in topics:
        messages.append(DoctorMessageList(
            user_id=user_id,
            doctor_id=doctor_id,
            topic=topic,
            diary=topic.diary
        ))
    DoctorMessageList.objects.bulk_create(messages)
