# coding:utf-8
"""名医大赏"""

import random
import operator
import datetime

from gm_types.error import ERROR as ERROR_CODES
from gm_types.gaia import FAMOUS_DOCTOR_JOIN_TYPE
from gm_types.gaia import PLATFORM_CHOICES
from api.models import ChannelGift
from api.tool.coupon_tool import _try_get_gift

from api.services.activities.famous_doctors import FamousDoctorService
from api.services.activities.famous_doctors import version_control_decorator, version_control, vote_valid_decorator, \
    sign_valid_decorator, award_valid_decorator
from api.services.activities.famous_doctors_conf import list_items
from api.tool.user_tool import get_user_from_context
from rpc.decorators import bind_context, bind
from rpc.tool.error_code import gen
from api.services.activities import famous_doctors_conf
from pay.tasks.famous_doctors_task import Two_or_Five_update_vote_count


@bind('api/famous_doctors/items')
@version_control_decorator
def famous_doctors_items(doc_type, version=None):
    """名医大赏项目列表"""
    famous_doctors_items = []
    if not version:  # 不传version走旧版逻辑
        famous_doctors_items = list_items()
    else:
        doc_type = int(doc_type) if doc_type else 0
        version, conf = version_control(version=version, key="items")  # 走新版逻辑去新的配置文件中寻找
        for c in conf:
            if c.get('doc_type') == doc_type:
                famous_doctors_items.append(c)
    return famous_doctors_items


@bind_context('api/famous_doctors/join')
@version_control_decorator
@sign_valid_decorator
def famous_doctors_join(ctx, doc_type, doc_id, item_ids, version=None):
    """报名"""
    doc_ids = [doc_id]
    docs_info = FamousDoctorService.list_docs_info(doc_type, doc_ids)
    if not docs_info:
        gen(ERROR_CODES.APPEND_NOT)
    else:
        is_join = FamousDoctorService.is_joined(doc_type, doc_id, version)
        if is_join:
            if doc_type == FAMOUS_DOCTOR_JOIN_TYPE.DOCTOR:
                gen(ERROR_CODES.DOCTOR_HAS_JOIN)
            else:
                gen(ERROR_CODES.HOSPITAL_HAS_JOIN)
        FamousDoctorService.join(doc_type, doc_id, item_ids, version)


@bind_context('api/famous_doctors/vote')
@version_control_decorator
@vote_valid_decorator  # 投票时间过滤筛选器
def famous_doctors_vote(ctx, doc_type, doc_id, item_id, platform, version=None):
    """投票"""
    user = get_user_from_context(ctx)
    if not user:
        gen(ERROR_CODES.LOGIN_REQUIRED)
    registrationer = FamousDoctorService.get_registrationer_by_doc_id(doc_type, doc_id, version)
    if not registrationer:
        if doc_type == FAMOUS_DOCTOR_JOIN_TYPE.DOCTOR:
            gen(ERROR_CODES.DOCTOR_NOT_JOIN)
        else:
            gen(ERROR_CODES.HOSPITAL_NOT_JOIN)
    if platform in [PLATFORM_CHOICES.ANDROID, PLATFORM_CHOICES.IPHONE]:
        is_app = True
    else:
        is_app = False
    vote_info = FamousDoctorService.user_vote_info(user.id, doc_type, doc_id, item_id, is_app)
    vote_sum = vote_info["vote_sum"]
    used_vote_cnt = vote_info["used_vote_cnt"]
    vote_item_sum = vote_info["vote_item_sum"]
    used_vote_item_cnt = vote_info["used_vote_item_cnt"]
    sum = FamousDoctorService.get_user_day_item_count(doc_id, is_app, user.id, doc_type, version)
    if vote_sum - used_vote_cnt <= 0:
        gen(ERROR_CODES.VOTE_COUNT_OUT)

    if vote_item_sum - used_vote_item_cnt <= 0:
        gen(ERROR_CODES.FD_EXCEED_VOTE_LIMIT)

    if sum >= 5:
        gen(ERROR_CODES.FD_EXCEED_VOTE_LIMIT)
    des = ''
    FamousDoctorService.vote(user.id, item_id, registrationer.id, platform)
    nowTime = datetime.datetime.now()
    is_get_reward = FamousDoctorService.find_reward(user.id, nowTime)
    if is_get_reward:
        des = '投票成功'
    else:
        count = FamousDoctorService.count_type(user.id)
        count = count.get('c', 0)
        des, now_reward = famous_doctors_conf.prize_des('202010', count)
        for reward in now_reward:
            FamousDoctorService.add_reward(user.id, reward.get('reward_type'), nowTime, des, '202010')
            if reward.get('reward_type'):
                if reward.get('reward_type') == 1:
                    """给用户发美分"""
                    points = FamousDoctorService.send_prize(user.id, '18', reward.get('prize'))
                elif reward.get('reward_type') == 2:
                    """给用户发礼包"""
                    channel_gift = ChannelGift.objects.get(id=reward.get('channel_gift_id'))
                    success, codes = _try_get_gift(channel_gift, user)
    cnt_v1 = 1
    FamousDoctorService.update_rank(doc_type, doc_id, [item_id], version, cnt_v1)
    cnt_v2 = 5
    cnt_v5 = 8
    FamousDoctorService.incr_used_vote_cnt(doc_type, doc_id, user.id, item_id, is_app)
    vote_cnt, rank, last_vote = FamousDoctorService.vote_rank_and_gap(doc_type, doc_id, item_id, version)
    # 添加虚拟投票
    Two_or_Five_update_vote_count.apply_async(
        args=(
            doc_type,
            doc_id,
            [item_id],
            version,
            item_id,
            registrationer.id,
            cnt_v2,
        ),
        countdown=120
    )
    Two_or_Five_update_vote_count.apply_async(
        args=(
            doc_type,
            doc_id,
            [item_id],
            version,
            item_id,
            registrationer.id,
            cnt_v5,
        ),
        countdown=300
    )

    return {
        "rank": rank,
        "vote_cnt": vote_cnt,
        "last_vote": last_vote,

        "vote_sum": vote_sum,
        "used_vote_cnt": used_vote_cnt + 1,

        "vote_item_sum": vote_item_sum,
        "used_vote_item_cnt": used_vote_item_cnt + 1,
        "des": des
    }


@bind('api/famous_doctors/info')
def famous_doctors_info(doc_type, reg_id=None, doc_id=None, version=None):
    """跟人当前参选排名信息"""
    registrationer = None
    version = version if version else '000000'
    if reg_id:
        registrationer = FamousDoctorService.get_registrationer_by_id(reg_id)
    elif doc_id:
        registrationer = FamousDoctorService.get_registrationer_by_doc_id(doc_type, doc_id, version)
    if not registrationer:
        if doc_type == FAMOUS_DOCTOR_JOIN_TYPE.DOCTOR:
            gen(ERROR_CODES.DOCTOR_NOT_JOIN)
        else:
            gen(ERROR_CODES.HOSPITAL_NOT_JOIN)

    doc_id = registrationer.doctor_id
    item_ids = FamousDoctorService.list_doctor_item_ids(doc_type, doc_id, version)
    items_conf = FamousDoctorService.get_items_dict_info()
    docs_info = FamousDoctorService.list_docs_info(doc_type, [doc_id])
    items = []
    for item_id in item_ids:
        items.append(items_conf[item_id])

    # wx_qr = FamousDoctorService.create_wx_qr(doc_type, doc_id, registrationer.id)
    result = {
        "items": items,
        "doc_info": docs_info.get(doc_id, {}),
        "wx_qr": "",  # 微信二维码 2020年以后由前端生成跳转不返值
        "reg_id": registrationer.id,
    }
    return result


@bind('api/famous_doctors/rank_info')
def famous_doctors_rank_info(doc_type, reg_id, version):
    """跟人当前参选排名信息"""
    registrationer = FamousDoctorService.get_registrationer_by_id(reg_id)
    if not registrationer:
        if doc_type == FAMOUS_DOCTOR_JOIN_TYPE.DOCTOR:
            gen(ERROR_CODES.DOCTOR_NOT_JOIN)
        else:
            gen(ERROR_CODES.HOSPITAL_NOT_JOIN)

    doc_id = registrationer.doctor_id
    item_ids = FamousDoctorService.list_doctor_item_ids(doc_type, doc_id, version)
    docs_info = FamousDoctorService.list_docs_info(doc_type, [doc_id])
    rank_info = {}
    for item_id in item_ids:
        rank_info[str(item_id)] = FamousDoctorService.vote_rank_and_gap(doc_type, doc_id, item_id, version)

    result = {
        "rank_info": rank_info,
        "doc_info": docs_info.get(doc_id, {})
    }

    return result


@bind('api/famous_doctors/join_list')
@version_control_decorator
def famous_doctors_join_list(doc_type, item_id, version=None, name=None, reg_id=None, offset=0):
    """投票列表"""
    version, conf = version_control(version)
    if isinstance(conf, dict):
        if not conf:
            rank_info_list = FamousDoctorService.list_rank_info_by_item_id(doc_type, item_id, version, offset)
            doc_ids = [item["doc_id"] for item in rank_info_list]

            docs_info = FamousDoctorService.list_docs_info(doc_type, doc_ids)

            res = []
            for rank_info in rank_info_list:
                doc_info = docs_info.get(rank_info["doc_id"])
                if not doc_info:
                    continue
                rank_info.update(doc_info)
                res.append(rank_info)

            res.sort(key=lambda item: -item["vote_cnt"])
            return res
        else:
            rank_info_list = FamousDoctorService.list_rank_info_by_item_id(doc_type, item_id, version, offset)
            doc_ids = [item["doc_id"] for item in rank_info_list]
            docs_info = FamousDoctorService.list_docs_info(doc_type, doc_ids)
            res = []
            for rank_info in rank_info_list:
                doc_info = docs_info.get(rank_info["doc_id"])
                if not doc_info:
                    continue
                if name:
                    if name in doc_info.get("name"):
                        pass
                    else:
                        continue
                if reg_id:
                    # 查询doc_id
                    doc_id = FamousDoctorService.get_doc_id_by_res_id(reg_id, version=version)
                    if not doc_id:
                        continue
                    doc_id = doc_id[0]["doctor_id"]
                    if doc_info.get("id") == doc_id:
                        pass
                    else:
                        continue
                rank_info.update(doc_info)
                res.append(rank_info)

            res.sort(key=lambda item: -item["vote_cnt"])
            return res


@bind("api/famous_doctors/result")
def famous_doctors_result():
    """名医大赏结果"""

    doctor_ids = []

    for item in famous_doctors_conf.famous_doctors_conf_map.get('202010').get('prize_doctors'):
        doctor_ids.extend(item["doctor_ids"])

    hospital_ids = []
    for item in famous_doctors_conf.famous_doctors_conf_map.get('202010').get('prize_hospitals'):
        hospital_ids.extend(item["hospital_ids"])

    data = {
        "hospitals": [],
        "doctors": [],
    }

    docotors_info = FamousDoctorService.list_docs_info(FAMOUS_DOCTOR_JOIN_TYPE.DOCTOR, doctor_ids)
    for item in famous_doctors_conf.famous_doctors_conf_map.get('202010').get('prize_doctors'):
        info = {
            "item_id": item["item_id"],
            "name": item["prize_name"],
            "items": []
        }
        for doctor_id in item["doctor_ids"]:
            doctor = docotors_info.get(doctor_id)
            if not doctor: continue
            info["items"].append(doctor)

        data["doctors"].append(info)

    hospitals_info = FamousDoctorService.list_docs_info(FAMOUS_DOCTOR_JOIN_TYPE.HOSPITAL, hospital_ids)
    for item in famous_doctors_conf.famous_doctors_conf_map.get('202010').get('prize_hospitals'):
        info = {
            "item_id": item["item_id"],
            "name": item["prize_name"],
            "items": []
        }
        for hospital_id in item["hospital_ids"]:
            hospital = hospitals_info.get(hospital_id)
            if not hospital: continue
            info["items"].append(hospital)

        data["hospitals"].append(info)

    return data


@bind("api/famous_doctors/read_conf")
def raed_conf():
    """读取配置文件时间用作倒计时使用"""
    startTime = famous_doctors_conf.famous_doctors_conf_map.get("202010"). \
        get("selection_time")

    endTime = famous_doctors_conf.famous_doctors_conf_map.get("202010"). \
        get("selection_end_time")
    data = {"startTime": startTime, "endTime": endTime}
    return data


@bind("api/famous_doctors/doctors_list")
def get_all_doctors_list(version, name=None, reg_code=None, doc_role=None, start_time=None, end_time=None):
    """获取报名医生的列表"""
    doctor_ids_and_types = FamousDoctorService.get_all_doctors_list(version)
    res = []
    for doc in doctor_ids_and_types:
        doctor_ids = doc.get("doctor_id")
        doc_ids = [doctor_ids]
        doc_type = doc.get("doctor_type")
        doc_type = str(doc_type)
        doc_role = str(doc_role)
        if doc_role:
            if doc_type == doc_role:
                pass
            else:
                continue
        docs_info = FamousDoctorService.list_docs_info(doc_type, doc_ids)

        for doc_info in docs_info.values():
            if not doc_info:
                continue
            if name:
                if name in doc_info.get('name'):
                    pass
                else:
                    continue
            doc_id = doc_info.get("id")
            reg_id = FamousDoctorService.get_reg_id_by_doc_id(doc_id, version)
            reg_code = str(reg_code)
            if reg_code:
                if str(reg_id[0].get("id")) == reg_code:
                    pass
                else:
                    continue
            items_result = FamousDoctorService.get_items(reg_id[0].get("id"))

            for item in items_result:
                doc_dict = {}
                doc_dict["item_id"] = item.get("item_id")
                doc_dict["vote_count"] = item.get("vote_count")
                createTime = str(item.get('create_time'))
                createTime = createTime.split('.', 1)[0]
                if start_time:
                    start_time = str(start_time)
                    if operator.le(start_time, createTime) == True:
                        pass
                    else:
                        continue
                if end_time:
                    end_time = str(end_time)
                    if operator.le(createTime, end_time) == True:
                        pass
                    else:
                        continue
                doc_dict["create_time"] = createTime
                doc_dict["reg_id"] = item.get("register_id")
                doc_dict["name"] = doc_info.get('name')
                doc_dict["doctor_type"] = doc_info.get('doctor_type')
                doc_dict['id'] = doc_info.get('id')

                res.append(doc_dict)
    result = {"data": res}
    return result


@bind("api/famous_doctors/get_reward")
@version_control_decorator
@award_valid_decorator
def get_reward(version, user_id):
    """'用户领奖获得美分"""
    reg_ids = FamousDoctorService.get_regids_by_user_id(user_id)
    if not reg_ids:
        return gen(ERROR_CODES.REWARD_DOCTOR_NOT)
    res = []
    for reg_id in reg_ids:
        doc_ids = FamousDoctorService.get_doc_id_by_res_id(reg_id.get("register_id"), version)
        for doc_id in doc_ids:
            res.append(doc_id)
    ret = []
    for i in res:
        if i not in ret:
            ret.append(i)
    doc_message = None
    for r in ret:
        for doctor in famous_doctors_conf.famous_doctors_conf_map.get('202010').get('prize_doctors'):
            if r.get('doctor_id') in doctor.get('doctor_ids'):
                doc_message = FamousDoctorService.user_get_reward(user_id, random.randint(100, 500), '18', version)
                break
        if doc_message:
            return doc_message
        else:
            for hospital in famous_doctors_conf.famous_doctors_conf_map.get('202010').get('prize_hospitals'):
                if r.get('doctor_id') in hospital.get('hospital_ids'):
                    hos_message = FamousDoctorService.user_get_reward(user_id, random.randint(100, 500), '18', version)
                    return hos_message
                else:
                    continue
            else:
                pass
    else:
        gen(ERROR_CODES.REWARD_DOCTOR_NOT)


@bind("api/famous_doctors/append")
@version_control_decorator
def famous_doctors_append(name, tel_phone, address, version):
    """名医大赏机构入驻"""
    is_append = FamousDoctorService.is_append(name)

    if is_append:
        gen(ERROR_CODES.APPEND_SAME)
    else:
        is_appendin = FamousDoctorService.is_appendin(name)
        if is_appendin:
            gen(ERROR_CODES.APPEND_SAME)
    FamousDoctorService.famous_doctors_append(name, tel_phone, address, version)


@bind("api/famous_doctors/find")
@version_control_decorator
def famous_doctors_find(version, start_time=None, end_time=None):
    """名医大赏后台系统新入驻机构列表展示"""
    version, conf = version_control(version)
    if isinstance(conf, dict):
        if not conf:
            return '参数不合法'
        else:
            res = []
            famous_doctors_list = FamousDoctorService.famous_doctors_find(version)
            for famous_doctors in famous_doctors_list:
                created_time = famous_doctors.get('created_time')
                created_time = str(created_time)
                famous_doctors['created_time'] = created_time

                if start_time:
                    startTime = str(start_time)
                    if (operator.le(startTime, created_time) == True):
                        pass
                    else:
                        continue
                if end_time:
                    endTime = str(end_time)
                    if (operator.le(created_time, endTime) == True):
                        pass
                    else:
                        continue
                res.append(famous_doctors)

            return res


@bind("api/famous_doctors/update_vote_count")
def update_vote_count(reg_id, item_id, count, user_id, version):
    """修改票数"""
    vote_count = FamousDoctorService.get_vote_count(reg_id=reg_id, item_id=item_id)
    vote_count = vote_count[0].get('vote_count')
    count = int(count)
    vote_count = int(vote_count)
    if count <= vote_count:
        gen(ERROR_CODES.VOTE_COUNT_NOT_UPDATE)
    else:
        FamousDoctorService.update_vote_count(reg_id=reg_id, item_id=item_id, count=count)
        add_num = count - vote_count
        FamousDoctorService.add_user(user_id=user_id, reg_id=reg_id, item_id=item_id, add_num=add_num)
        res = FamousDoctorService.get_doc_id_and_doc_type(reg_id=reg_id)
        FamousDoctorService.update_rank(res[0].get('doctor_type'), res[0].get('doctor_id'), [item_id], version,
                                        add_num)
        return gen("更改成功")
