# coding=utf-8
from __future__ import unicode_literals, absolute_import, print_function
import datetime, json
import itertools

from django.utils import timezone
from django.utils.html import escape
from django.db.models import Q, Max, Count

from gm_types.gaia import QUESTION_ORDER_TYPE
from gm_types.error import ERROR as CODES
from gm_rpcd.all import bind

from utils.rpc import rpc_client, gen, logging_exception
from qa.utils.decorator import listing
from qa.models import Question, QuestionDoctor, Answer, AnswerReply
from talos.libs.datetime_utils import get_timestamp_or_none
from talos.services.user import UserService
from talos.models.doctor import DoctorMessageList



@bind('qa/question/doctor/filter')
def question_filter():
    data = {
        'provinces': rpc_client['api/province/list'](display_in_filter=True).unwrap(),
    }
    types = [QUESTION_ORDER_TYPE.DOCTOR_LASTEST, QUESTION_ORDER_TYPE.DOCTOR_RECOMMEND]
    data['orders'] = [{'id': item, 'name': QUESTION_ORDER_TYPE.getDesc(item)}
                      for item in types]
    return data


@bind("qa/question/doctor/list")
@listing()
def question_list_for_doctor(start_num, count=10, province_id=None, order_by=QUESTION_ORDER_TYPE.DOCTOR_LASTEST):
    questions = rpc_client['api/question/filter'](offset=start_num, size=count,
                                                  province_id=province_id, sort_type=order_by).unwrap()['question_ids']

    question_ids = [item['question'] for item in questions]
    questions = Question.objects.filter(id__in=question_ids)
    q_dict = {}
    for question in questions:
        q_dict[question.id] = question
    data = []
    for q_id in question_ids:
        question = q_dict.get(q_id)
        if question:
            data.append(question.data_for_doctor())
    return {
        'questions': data,
    }


@bind('qa/question/add_relate_doctor')
def add_question_related_to_doctor(question_id, doctor_ids):
    # 问题关联的tag,通过美购tag关联相关医生
    if question_id and doctor_ids:
        try:
            question = Question.objects.get(id=question_id)
            insert_lst = []
            for d_id in doctor_ids:
                insert_lst.append(QuestionDoctor(question=question, doctor_id=d_id))
            QuestionDoctor.objects.bulk_create(insert_lst)
            return gen(CODES.SUCCESS)

        except Question.DoesNotExist:
            return gen(CODES.QUESTION_NOT_FOUND)

        except:
            logging_exception()
            return gen(CODES.UPDATE_FAIL)
    else:
        return gen(CODES.PARAMS_INVALID)


@bind('qa/question/related_to_doctor')
def question_lst_related_to_doctor(doctor_id, offset=0, size=10):
    # 医生被邀请的问题列表
    if not doctor_id:
        return gen(CODES.PARAMS_INVALID)

    try:
        re_data_lst = []
        question_doctor_info = QuestionDoctor.objects.filter(
            doctor_id=doctor_id).order_by('-create_time')[offset:offset + size]
        for item in question_doctor_info:
            re_data_lst.append({
                'question_id': item.question.id,
                'question_title': item.question.title,
                'user': item.question.user.nickname,
                'qusetion_time': item.question.create_time.strftime("%m-%d %H:%M"),
            })
        return re_data_lst
    except Question.DoesNotExist:
        return gen(CODES.QUESTION_NOT_FOUND)
    except:
        logging_exception()
        return gen(CODES.UPDATE_FAIL)


@bind('qa/question/doctor_unread_count')
def doctor_q_unread_count(doctor_id):
    # 医生收到的问题未读数量通知
    if not doctor_id:
        return gen(CODES.PARAMS_INVALID)

    try:
        q_cout = QuestionDoctor.objects.filter(doctor_id=doctor_id, unread=True).count()
        return q_cout
    except:
        logging_exception()
        return 0


@bind('qa/question/daily_push_doctors')
def get_doctorid_to_push(start_t, end_t):
    # 获取每日需要推送的医生列表
    start_t = start_t if start_t else datetime.datetime.now() + datetime.timedelta(-1)
    end_t = end_t if start_t else timezone.now()

    try:
        doctor_ids = QuestionDoctor.objects.filter(
            create_time__range=(
                start_t, end_t)).values_list(
            'doctor_id', flat=True).distinct()
        return {'doctor_ids': json.dumps(doctor_ids)}
    except :
        logging_exception()
        return {'doctor_ids': []}


@bind('qa/question/doctor_read_votes')
def read_votes(doctor_id):
    # 将未读消息已读
    if not doctor_id:
        return gen(CODES.PARAMS_INVALID)

    try:
        QuestionDoctor.objects.filter(doctor_id=doctor_id, unread=True).update(unread=False)
        return gen(CODES.SUCCESS)
    except:
        logging_exception()
        return gen(CODES.UPDATE_FAIL)


@bind("qa/question/list_messages_by_doctor_id")
def get_doctor_push_question_by_doctor_id(doctor_id, sort_type=None, offset=0, count=10):

    if sort_type == "invite_time":
        sort = '-created_time'
    else:
        sort = '-created_time'

    query = Q(is_online=True, question__isnull=False, doctor_id=doctor_id)

    messages_qs = DoctorMessageList.objects.filter(query).order_by(sort)

    cnt = messages_qs.count()
    if not cnt:
        return {"total": cnt, "questions": []}

    messages = messages_qs[offset: offset + count].select_related("question")
    users = UserService.get_users_by_user_ids([item.user_id for item in messages])

    cities_ids = [user.current_city_id for user in users.values() if user.current_city_id]
    cities = {}
    if cities_ids:
        try:
            cities = rpc_client['api/city/city_by_ids'](city_ids=cities_ids).unwrap()
        except:
            logging_exception()

    # 获取问题最后回答时间
    answers = Answer.objects.filter(is_online=True, question_id__in=[ms.question_id for ms in messages])\
        .values_list("question_id").annotate(reply_time=Max('create_time'))
    reply_time_info = {question_id: reply_time for question_id, reply_time in answers}

    # 获取一级评论数 + 回答数
    answers = Answer.objects.filter(is_online=True, question_id__in=[ms.question_id for ms in messages]) \
        .values_list("question_id").annotate(cnt=Count('*'))
    reply_cnt_info = {question_id: cnt for question_id, cnt in answers}

    answer_ids = Answer.objects.filter(is_online=True, question_id__in=[ms.question_id for ms in messages]) \
        .values_list("question_id", "id")
    answer_ids_info = {}
    for question_id, answer_id in answer_ids:
        answer_ids_info[answer_id] = question_id

    replies = AnswerReply.objects.filter(answer_id__in=list(answer_ids_info.keys()),
                                         first_reply=None, is_online=True).values_list("answer_id"). \
        annotate(cnt=Count('*'))
    for answer_id, c in replies:
        reply_cnt_info[answer_ids_info[answer_id]] += c

    res = {"total": cnt, "questions": []}
    for item in messages:
        user = users.get(item.user_id)
        info = {
            "id": item.question.id,
            "title": item.question.title,
            "tags": [tag.tag for tag in item.question.tags if tag.tag],
            "created_time": get_timestamp_or_none(item.question.create_time),
            "update_time": get_timestamp_or_none(reply_time_info.get(item.question.id)),
            "reply_num": reply_cnt_info.get(item.question_id, 0),
            "status": item.process_status,
            "author": {
                "id": user.id if user else None,
                "nickname": user.nickname if user else None,
                'current_city_id': user.current_city_id,
                'current_city_name': cities.get(user.current_city_id, {}).get("name"),
                'city_id': user.city_id,
                'city_name': user.city_name,
            }
        }
        res["questions"].append(info)

    return res
