# coding: utf-8
from rpc.decorators import bind, bind_context
from rpc.tool.log_tool import logging_exception
from django.conf import settings
import datetime
from dingtalkchatbot.chatbot import DingtalkChatbot
from api.models import transaction,BDTransfer,BDTransferOperationRecord
from django.db.models import Q
from rpc.exceptions import RPCNotFoundException
from django.contrib.auth.models import User
from api.tool.user_tool import get_user_from_context
from django.db.models import ManyToManyField, Q
from gm_types.gaia import OPERATION_ACTION
from hera.models import BDTransferAutoAssignor, ScheduleTime, BDTransferUserSchedule,BDTransferAssignRecord,TransferRate
import sys
reload(sys)
sys.setdefaultencoding("utf8")

uri_pre = 'hera/bdtransfer/'


# 自动分配成功需要发送通知
def send_notify(user_id_2_bdtransfer_id_list, user_id_2_username , at_phone):
    '''

    :param ding_2_bdtransfer_id_list: {'ding_num':[bdtransfer_id list]}
    :param ding_2_username: {'ding_num':username}
    '''
    msg = ''
    try:
        for user_id in user_id_2_bdtransfer_id_list:
            for bdtransfer_id in user_id_2_bdtransfer_id_list[user_id]:
                msg += '【线索分发通知】你({})有一条新分发转诊线索（线索id：{}），请注意跟进！\n'.format(user_id_2_username[user_id],bdtransfer_id)
            msg += '\n'
        if msg:
            webhook = 'https://oapi.dingtalk.com/robot/send?access_token={}'.format(settings.ACCESS_TOKEN)
            xiaoding = DingtalkChatbot(webhook)
            haha = xiaoding.send_text(msg=msg, at_mobiles=at_phone)
    except Exception:
        logging_exception()


@bind(uri_pre + 'auto_assignor')
def get_auto_assignor(username=None):
    '''

    :return:
    {
        user_id:
        username:
        ding:
        now:
        top:
        low:
        count:
        rate:
        is_active:
        is_f:

    }
    '''
    clock = datetime.datetime.now().hour
    schedule = ScheduleTime.objects.first()
    morning = 0
    night = 0
    if schedule.morning_start <= clock < schedule.morning_end:
        morning = 1
    if schedule.night_start <= clock < schedule.night_end:
        night = 1
    cur_date = datetime.date.today()
    # 排班表
    schedule_dict = {}
    # 在工作时间段执行查询排班表
    user_id = None
    if username:
        search_user = User.objects.filter(username=username,is_active=True).first()
        if not search_user:
            return []
        user_id = search_user.id

    if morning or night:
        s_q = Q(date=cur_date)
        if user_id:
            s_q &=Q(user_id=user_id)
        if morning and night:
            s_q &= (Q(morning=True)|Q(night=True))
        elif morning:
            s_q &= Q(morning=True)
        elif night:
            s_q &= Q(night=True)
        schedule_cur = BDTransferUserSchedule.objects.filter(s_q)
        for single in schedule_cur:
            schedule_dict[single.user_id] = [single.morning, single.night]
    ret = []
    user_list = []

    if user_id:
        assignor_cur = BDTransferAutoAssignor.objects.filter(user_id=user_id)
    else:
        assignor_cur = BDTransferAutoAssignor.objects.all()
    for item in assignor_cur:
        user_list.append(item.user.id)
        ret_dict = {
            'user_id':item.user_id,
            'username':item.user.username,
            'ding':item.ding,
            'top':item.top,
            'low':item.low,
            'is_active':1 if item.is_active else 0,
            'is_f': 1 if item.is_f else 0,
            'now': 1 if schedule_dict.get(item.user_id) else 0,
        }
        ret.append(ret_dict)

    # 每天分配数量
    user_count = {}
    record_cur = BDTransferAssignRecord.objects.filter(user_id__in=user_list,date=cur_date)
    for single_record in record_cur:
        user_count[single_record.user_id]= single_record.count

    # 转化率
    user_rate = {}
    yestoday = cur_date + datetime.timedelta(days=-1)
    rate_cur = TransferRate.objects.filter(date=yestoday)

    x_max = 0
    y_max = 0
    user_id_2_x_y = {}

    for single_item in rate_cur:
        if not x_max:
            x_max = single_item.avg_30_inversion_rate
        else:
            if x_max < single_item.avg_30_inversion_rate:
                x_max = single_item.avg_30_inversion_rate
        if not y_max:
            y_max = single_item.avg_30_order_amount
        else:
            if y_max < single_item.avg_30_order_amount:
                y_max = single_item.avg_30_order_amount

        if int(single_item.consultant_id) in user_list:
            user_id_2_x_y[int(single_item.consultant_id)] = [single_item.avg_30_inversion_rate, single_item.avg_30_order_amount]

    for user_id in user_list:
        x = user_id_2_x_y.get(user_id,[0,0])[0]
        y = user_id_2_x_y.get(user_id,[0,0])[1]
        rate = ((x/x_max)*100)*0.7 + ((y/y_max)*100)*0.3
        user_rate[user_id] = round(rate,2)

    for single_ret in ret:
        user_id = single_ret['user_id']
        single_ret['rate'] = user_rate.get(user_id,0)
        single_ret['count'] = user_count.get(user_id, 0)
    # ret = [
    #     {'user_id': 1, 'username': "123", 'ding': '2313213213213', 'now': 1, "rate": 0.2, "count": 20, "top": 60,
    #      "low": 10, "is_active": 1, 'is_f': 0},
    #     {'user_id': 2, 'username': "345", 'ding': '234234242424', 'now': 0, "rate": 0.01, "count": 90, "top": 80,
    #      "low": 10, "is_active": 1, 'is_f': 1},
    #     {'user_id': 3, 'username': "456", 'ding': '2342342323', 'now': 1, "rate": 0.00001, "count": 2, "top": 70,
    #      "low": 10, "is_active": 0, 'is_f': 0},
    #     {'user_id': 4, 'username': "789", 'ding': "234342342342343", 'now': 1, "rate": 5, "count": 80, "top": 80,
    #      "low": 10, "is_active": 1, 'is_f': 0},
    #     {'user_id': 5, 'username': "545", 'ding': "2343423423", 'now': 0, "rate": 5, "count": 80, "top": 80, "low": 10,
    #      "is_active": 1, 'is_f': 0},
    # ]

    return ret

#  线索自动分配顾问 上下限设置
@bind(uri_pre + 'auto_assignor_limit')
def auto_assign_limit(user_id, top=None, low=None):

    assignor = BDTransferAutoAssignor.objects.filter(user_id=user_id).first()
    if not assignor:
        raise RPCNotFoundException
    if top is not None and top>=assignor.low:
        assignor.top = top
    if low is not None and low<=assignor.top:
        assignor.low = low
    assignor.save()
    return assignor.user_id


# 线索自动分配顾问 封禁、解禁
@bind(uri_pre + 'auto_assignor_active')
def auto_assign_active(user_id):
    assignor = BDTransferAutoAssignor.objects.filter(user_id=user_id).first()
    if not assignor:
        # raise RPCNotFoundException
        return 0

    assignor.is_active = not assignor.is_active
    assignor.save()
    return assignor.user_id


# 线索自动分配顾问 强制接收线索、解除强制
@bind(uri_pre + 'auto_assignor_f')
def auto_assign_f(user_id):
    assignor = BDTransferAutoAssignor.objects.filter(user_id=user_id).first()
    if not assignor:
        # raise RPCNotFoundException
        return 0

    assignor.is_f = not assignor.is_f
    assignor.save()
    return assignor.user_id

# 线索自动分配顾问 ding
@bind(uri_pre + 'auto_assignor_ding')
def auto_assign_ding(user_id, ding):
    assignor = BDTransferAutoAssignor.objects.filter(user_id=user_id).first()
    if not assignor:
        # raise RPCNotFoundException
        return 0

    assignor.ding = ding
    assignor.save()
    return assignor.user_id


#  自动分配转诊顾问添加
@bind(uri_pre + 'auto_assignor_add')
def auto_assignor_add(user_id,new_ding):
    cur_user = User.objects.filter(id=user_id,is_active=True).first()
    if not cur_user:
        return {'data':user_id, 'code':1, 'message':'此顾问账号不存在'}
    assingor = BDTransferAutoAssignor.objects.filter(user=cur_user)
    if assingor:
        return {'data':user_id, 'code':1, 'message':'顾问已经存在，请勿重复创建！'}
    BDTransferAutoAssignor.objects.create(user=cur_user, ding=new_ding)
    return {'data':user_id, 'code':0, 'message':''}

#  自动转诊顾问删除
@bind(uri_pre + 'auto_assignor_del')
def auto_assignor_del(user_id):
    cur_user = BDTransferAutoAssignor.objects.filter(user_id=user_id).first()
    if not cur_user:
        return
    # with transaction.atomic():
    cur_user.delete()
        # BDTransferUserSchedule.objects.filter(user_id=user_id).delete()
    return cur_user.user_id


#  转诊顾问排班管理列表
@bind(uri_pre + 'assignor_schedule')
def assignor_schedule():
    cur_date = datetime.datetime.today()
    assignor_id_list = BDTransferAutoAssignor.objects.all().values_list("user_id")

    schedule_cur = BDTransferUserSchedule.objects.filter(date__gte=cur_date, user_id__in=assignor_id_list)
    ret_dict = {}
    for single_schedule in schedule_cur:
        if single_schedule.morning:
            ret_dict.setdefault(single_schedule.date.strftime('%Y/%m/%d'),[[],[]])[0].append(single_schedule.user.username)
        if single_schedule.night:
            ret_dict.setdefault(single_schedule.date.strftime('%Y/%m/%d'), [[], []])[1].append(single_schedule.user.username)

    ret = []

    for item in ret_dict:
        item_dict = {
            'date':item,
            'morning':ret_dict[item][0],
            'night':ret_dict[item][1]
        }
        ret.append(item_dict)

    # ret = [
    #     {
    #         'date':u"2020/03/10",
    #         'morning':[u'张三',u'李四'],
    #         'night':[u'李四']
    #     },
    #     {
    #         'date': u"2020/03/02",
    #         'morning': [u'李四'],
    #         'night': [u'张三']
    #     },
    #     {
    #         'date': u"2020/03/09",
    #         'morning': [u'王五', u'李四'],
    #         'night': [u'李四']
    #     },
    #     {
    #         'date': u"2020/03/01",
    #         'morning': [u'王五', u'李四'],
    #         'night': [u'李四']
    #     },
    # ]
    ret.sort(key=lambda x:x['date'])

    return ret

# 排班时间查询
@bind(uri_pre + 'schedule_time')
def schedule_time():
    schedule = ScheduleTime.objects.first()
    if not schedule:
        # raise RPCNotFoundException
        return {'morning_start': 8, 'morning_end': 16,
         'night_start': 14, 'night_end': 20}

    return {'morning_start':schedule.morning_start,'morning_end':schedule.morning_end,'night_start':schedule.night_start,'night_end':schedule.night_end}


# 转诊顾问排班管理excel检查
@bind(uri_pre + 'check_schedule_excel')
def check_schedule_excel(excel_list):
    # 自动分配人员配置信息
    auto_user_id_username={}
    auto_assignor_cur = BDTransferAutoAssignor.objects.all()
    for assignor in auto_assignor_cur:
        auto_user_id_username[assignor.user_id] = assignor.user.username

    # 所有可以排班的顾问名称
    username_list = auto_user_id_username.values()

    # [[日期 原始早班 原始晚班 新早班 新晚班 错误信息]]
    ret = []
    # excel中涉及到的日期
    date_list = []
    # 是否有错误
    code = 0
    # 原始排班
    date_user = {}
    for item_list in excel_list:
        date_str = item_list[0]
        ret_item_list = []
        try:
            date_object = datetime.datetime.strptime(date_str, '%Y/%m/%d').date()
            if date_object in date_list:
                ret_item_list = [date_str, [],[], item_list[1],item_list[2],"日期重复"]
                ret.append(ret_item_list)
                code = 1
                continue
            date_list.append(date_object)

        except:
            ret_item_list = [date_str, [],[], item_list[1],item_list[2],"日期(格式)错误"]
            ret.append(ret_item_list)
            code = 1
            continue

        morning_list = item_list[1].split(',')
        morning_user_list = []
        for morning_item in morning_list:
            morning_item = morning_item.strip()
            if morning_item:
                if morning_item not in username_list:
                    ret_item_list = [date_str, [],[], item_list[1],item_list[2],"顾问账号({})错误".format(morning_item)]
                    code = 1
                    break
                morning_user_list.append(morning_item)
        night_list = item_list[2].split(',')
        night_user_list = []
        for night_item in night_list:
            night_item = night_item.strip()
            if night_item:
                if night_item not in username_list:
                    ret_item_list = [date_str, [],[], item_list[1],item_list[2],"顾问账号({})错误".format(night_item)]
                    code = 1
                    break
                night_user_list.append(night_item)
        if not (morning_user_list and night_user_list) and not ret_item_list:
            ret_item_list = [date_str, [], [], item_list[1], item_list[2], "早、晚班不能为空"]
            code = 1

        if not ret_item_list:
            ret_item_list = [date_str, [],[], item_list[1],item_list[2],""]

        ret.append(ret_item_list)
    if date_list:
        schedule_cur = BDTransferUserSchedule.objects.filter(date__in=date_list)
        for single_schedule in schedule_cur:
            if single_schedule.morning:
                date_user.setdefault(single_schedule.date.strftime('%Y/%m/%d'), [[], []])[0].append(single_schedule.user.username)
            if single_schedule.night:
                date_user.setdefault(single_schedule.date.strftime('%Y/%m/%d'), [[], []])[1].append(single_schedule.user.username)

        for single_date_schedule_list in ret:
            if single_date_schedule_list[0] in date_user:
                single_date_schedule_list[1] = u','.join(date_user[single_date_schedule_list[0]][0])
                single_date_schedule_list[2] = u','.join(date_user[single_date_schedule_list[0]][1])

                if not single_date_schedule_list[5]:
                    if (single_date_schedule_list[1] or single_date_schedule_list[2]) and not(single_date_schedule_list[3] or single_date_schedule_list[4]):
                        single_date_schedule_list[5] = u'当日排班被清空'
                        code = 1


    # ret = [
    #     ['2020/01/01','wxj、wxj','','wxj','',''],
    #     ['2020/01/03','wxj','wxj','','',''],
    #     ['2020/01/03','wxj','wxj','','','日期重复'],
    #     ['2020/03/02','wxj','','','wxj','人员错误']
    # ]
    # code = 0

    return {'ret':ret, 'code':code}


#  转诊顾问排班管理 修改
@bind(uri_pre + 'edit_assignor_schedule')
def edit_assignor_schedule(excel_list):
    auto_user_id_username = {}
    auto_assignor_cur = BDTransferAutoAssignor.objects.all()
    for assignor in auto_assignor_cur:
        auto_user_id_username[assignor.user_id] = assignor.user.username

    id_list = auto_user_id_username.keys()
    username_list = auto_user_id_username.values()
    # {
    #     date:{
    #         id:[0,1],
    #         id:[1,1]
    #     },,,
    # }
    date_user_id_morning_night = {}

    for single_schedule_list in excel_list:
        try:
            date_object = datetime.datetime.strptime(single_schedule_list[0], '%Y/%m/%d').date()
            morning_user_list = single_schedule_list[1].split(',')
            night_user_list = single_schedule_list[2].split(',')
            for single_morning_user in morning_user_list:
                single_morning_user = single_morning_user.strip()
                if single_morning_user:
                    user_id = id_list[username_list.index(single_morning_user)]
                    date_user_id_morning_night.setdefault(date_object,{}).setdefault(user_id,[0,0])[0] = 1

            for single_night_user in night_user_list:
                single_night_user = single_night_user.strip()
                if single_night_user:
                    user_id = id_list[username_list.index(single_night_user)]
                    date_user_id_morning_night.setdefault(date_object,{}).setdefault(user_id,[0,0])[1] = 1

            if not date_user_id_morning_night.get(date_object,None):
                date_user_id_morning_night[date_object] = {}
        except Exception as e:
            logging_exception(e)
            return {'code':1,'message':'信息字段错误'}

    with transaction.atomic():
        BDTransferUserSchedule.objects.filter(date__in=date_user_id_morning_night.keys()).delete()
        object_list = []
        for single_date in date_user_id_morning_night:
            date_dict = date_user_id_morning_night[single_date]
            for single_user_id in date_dict:
                object_list.append(BDTransferUserSchedule(date=single_date, user_id=single_user_id,
                                                          morning=date_dict[single_user_id][0], night=date_dict[single_user_id][1]))
        if object_list:
            BDTransferUserSchedule.objects.bulk_create(object_list)

    return {'code':0, 'message':''}


# 线索创建后自动分发
def auto_assign_single_bdtransfer(bdtransfer_id_list):
    last_assign = BDTransferOperationRecord.objects.filter(action=OPERATION_ACTION.ASSIGN, content__contains='自动').order_by('-operate_time').first()
    if last_assign:
        # 上次分配的人员
        last_user_id = last_assign.bdtransfer.current_follow_up_consultant_id
    else:
        last_assign = BDTransferOperationRecord.objects.filter(action=OPERATION_ACTION.ASSIGN).order_by('-operate_time').first()
        # 上次分配的人员
        last_user_id = last_assign.bdtransfer.current_follow_up_consultant_id

    # 当前循环的前几位人员
    last_loop_user_id_list = []

    message = ''

    # 当前时间
    clock = datetime.datetime.now().hour

    # 早晚班时间
    schedule = ScheduleTime.objects.first()

    morning = 0
    night = 0
    if schedule.morning_start <= clock < schedule.morning_end:
        morning = 1
    if schedule.night_start <= clock < schedule.night_end:
        night = 1

    # 当前日期
    cur_date = datetime.datetime.today()

    # 当前在班用户id列表
    cur_user_id_list = []

    if morning or night:
        s_q = Q(date=cur_date)
        if morning and night:
            s_q &= (Q(morning=True) | Q(night=True))
        elif morning:
            s_q &= Q(morning=True)
        elif night:
            s_q &= Q(night=True)
        cur_user_id_list = list(BDTransferUserSchedule.objects.filter(s_q).values_list('user_id',flat=True))
    s_q = Q(is_f=True)
    if cur_user_id_list:
        s_q |= (Q(user_id__in=cur_user_id_list) & Q(is_active=True))

    # 当前在班 或者强制接收线索人员列表
    auto_assignor_object_list = BDTransferAutoAssignor.objects.filter(s_q)

    # 当前没有在班人员 也没有强制接收人员
    if not auto_assignor_object_list:
        message = u"当前无在班、强制接收线索人员！"
        return {'message': message, 'code': 1}

    # 当前在班 或者强制接收线索人员id列表
    available_user_id_list = []
    # 用户id对应ding
    user_id_2_ding = {}
    # 用户id对应用户姓名
    user_id_2_username = {}
    # 当前在班 人员 信息 列表
    now_auto_assignor_list = []
    # 当前强制接收线索 人员 信息 列表
    f_auto_assignor_list = []

    for single_item in auto_assignor_object_list:
        if single_item.user_id not in available_user_id_list:
            available_user_id_list.append(single_item.user_id)

        # 添加当前在班人员信息
        if single_item.user_id in cur_user_id_list:
            now_auto_assignor_list.append(
                {
                    'user_id': single_item.user_id,
                    'top': single_item.top,
                    'low': single_item.low
                }
            )
        # 添加强制接收线索人员信息
        if single_item.is_f:
            f_auto_assignor_list.append(
                {
                    'user_id': single_item.user_id,
                    'top': single_item.top,
                    'low': single_item.low
                }
            )
        # 添加 用户id对应ding账号
        user_id_2_ding[single_item.user_id] = single_item.ding
        # 添加 用户id对应用户username
        user_id_2_username[single_item.user_id] = single_item.user.username

    # 当前在班 或者强制接收线索人员 user_id : 当日分配数量
    user_id_2_count = {}
    # 当前在班 或者强制接收线索人员 user_id : rate
    user_id_2_rate = {}

    user_count_list = BDTransferAssignRecord.objects.filter(user_id__in=available_user_id_list, date=cur_date)
    for single_item in user_count_list:
        user_id_2_count[single_item.user_id] = single_item.count
    x_max = 0
    y_max = 0
    user_id_2_x_y = {}
    yestoday = cur_date + datetime.timedelta(days=-1)
    user_rate_list = TransferRate.objects.filter(date=yestoday)
    for single_item in user_rate_list:
        if not x_max:
            x_max = single_item.avg_30_inversion_rate
        else:
            if x_max < single_item.avg_30_inversion_rate:
                x_max = single_item.avg_30_inversion_rate
        if not y_max:
            y_max = single_item.avg_30_order_amount
        else:
            if y_max < single_item.avg_30_order_amount:
                y_max = single_item.avg_30_order_amount

        if int(single_item.consultant_id) in available_user_id_list:
            user_id_2_x_y[int(single_item.consultant_id)] = [single_item.avg_30_inversion_rate,
                                                             single_item.avg_30_order_amount]

    for user_id in available_user_id_list:
        x = user_id_2_x_y.get(user_id, [0, 0])[0]
        y = user_id_2_x_y.get(user_id, [0, 0])[1]
        rate = ((x / x_max) * 100) * 0.7 + ((y / y_max) * 100) * 0.3
        user_id_2_rate[user_id] = rate

    # 当前在班人员最低转化率
    low_rate = 0
    # 当前在班人员最低转化率对应底限
    low_rate_low = 0

    # 更新当前在班人员的转化率
    for item in now_auto_assignor_list:
        item['rate'] = user_id_2_rate.get(item['user_id'], 0)

    # 根据转化率排序
    now_auto_assignor_list.sort(key=lambda x: x['rate'], reverse=True)

    # 查找在班人员中 转化率最低人员 转化率、低限
    if now_auto_assignor_list:
        low_rate = now_auto_assignor_list[-1]['rate'] if now_auto_assignor_list[-1]['rate'] > 1 else 1
        low_rate_low = now_auto_assignor_list[-1]['low']

    # 分配阶段
    level = 1

    # 是否计算过 计算上限
    is_com = 0

    # 是否更新过强制接收线索人员 成单率
    is_f_com = 0

    # 用户id 对应分配的 线索id列表
    user_id_2_bdtransfer = {}

    # 第几次循环
    i = 1

    # 是否已经使用过上次分配人员
    flag = 0

    while bdtransfer_id_list:
        # 每次循环后 算出任务id个数
        old_length = len(bdtransfer_id_list)
        if not cur_user_id_list:
            # 当前没有在班人员 直接进入阶段4
            level = 4

        if level == 1:
            # 第一阶段
            for single_assignor in now_auto_assignor_list:
                if not bdtransfer_id_list:
                    break
                cur_user_id = single_assignor['user_id']
                if i == 1 and not flag:
                    if last_user_id not in last_loop_user_id_list:
                        last_loop_user_id_list.append(cur_user_id)
                        continue
                if user_id_2_count.setdefault(cur_user_id, 0) < single_assignor['low']:
                    user_id_2_bdtransfer.setdefault(cur_user_id, []).append(bdtransfer_id_list.pop())
                    user_id_2_count[cur_user_id] = user_id_2_count.setdefault(cur_user_id, 0) + 1
                    if cur_user_id in last_loop_user_id_list:
                        flag = 1
            else:
                if i == 2:
                    # 经过第二轮轮分配后 没有分配出任务 进入第二阶段
                    if old_length == len(bdtransfer_id_list):
                        i = 1
                        last_loop_user_id_list = []
                        level = 2
                else:
                    i += 1

        elif level == 2:
            # 第二阶段

            # 判断是否计算过 计算上限
            if not is_com:
                for single_assignor in now_auto_assignor_list:
                    single_rate = single_assignor['rate'] if single_assignor['rate'] > 1 else 1
                    com_top = round(((single_rate / low_rate) * low_rate_low))
                    single_assignor['com_top'] = com_top if com_top < single_assignor['top'] else single_assignor['top']
                is_com = 1

            for single_assignor in now_auto_assignor_list:
                if not bdtransfer_id_list:
                    break
                cur_user_id = single_assignor['user_id']
                if i == 1 and not flag:
                    if last_user_id not in last_loop_user_id_list:
                        last_loop_user_id_list.append(cur_user_id)
                        continue

                if user_id_2_count[cur_user_id] < single_assignor['com_top']:
                    user_id_2_bdtransfer.setdefault(cur_user_id, []).append(bdtransfer_id_list.pop())
                    user_id_2_count[cur_user_id] += 1
                    if cur_user_id in last_loop_user_id_list:
                        flag = 1
            else:
                if i == 2:
                    # 经过一轮分配后 没有分配出任务 进入第三阶段
                    if old_length == len(bdtransfer_id_list):
                        i = 1
                        last_loop_user_id_list = []
                        level = 3
                else:
                    i += 1

        elif level == 3:
            # 第三阶段
            for single_assignor in now_auto_assignor_list:
                if not bdtransfer_id_list:
                    break
                cur_user_id = single_assignor['user_id']
                if i == 1 and not flag:
                    if last_user_id not in last_loop_user_id_list:
                        last_loop_user_id_list.append(cur_user_id)
                        continue

                if user_id_2_count[cur_user_id] < single_assignor['top']:
                    user_id_2_bdtransfer.setdefault(cur_user_id, []).append(bdtransfer_id_list.pop())
                    user_id_2_count[cur_user_id] += 1
                    if cur_user_id in last_loop_user_id_list:
                        flag = 1
            else:

                if i == 2:
                    if old_length == len(bdtransfer_id_list):
                        i = 1
                        last_loop_user_id_list = []
                        level = 4
                else:
                    i += 1
        else:
            # 第四阶段
            # 没有强制接收线索人员 退出
            if not f_auto_assignor_list:
                break

            if not is_f_com:
                for single_assignor in f_auto_assignor_list:
                    single_assignor['rate'] = user_id_2_rate.get(single_assignor['user_id'], 0)
                f_auto_assignor_list.sort(key=lambda x: x['rate'], reverse=True)

            for single_assignor in f_auto_assignor_list:
                if not bdtransfer_id_list:
                    break

                cur_user_id = single_assignor['user_id']
                if i == 1 and not flag:
                    if last_user_id not in last_loop_user_id_list:
                        last_loop_user_id_list.append(cur_user_id)
                        continue
                user_id_2_bdtransfer.setdefault(cur_user_id, []).append(bdtransfer_id_list.pop())
                user_id_2_count[cur_user_id] = user_id_2_count.setdefault(cur_user_id, 0) + 1
                if cur_user_id in last_loop_user_id_list:
                    flag = 1
            else:
                i += 1

    # 分配成功人员 发送钉钉的手机号
    at_phone = []

    for user_id in user_id_2_bdtransfer:
        at_phone.append(user_id_2_ding[user_id])

    return {
        'message': message,
        'code': 0,
        'last': bdtransfer_id_list,
        'assign': user_id_2_bdtransfer,
        'at_phone': at_phone,
        'user_id_2_username': user_id_2_username,
        'user_id_2_count': user_id_2_count
    }


# 线索自动分发
def auto_assign_bdtransfer(bdtransfer_id_list):
    message = ''

    # 当前时间
    clock = datetime.datetime.now().hour

    # 早晚班时间
    schedule = ScheduleTime.objects.first()

    morning = 0
    night = 0
    if schedule.morning_start <= clock < schedule.morning_end:
        morning = 1
    if schedule.night_start <= clock < schedule.night_end:
        night = 1

    # 当前日期
    cur_date = datetime.datetime.today()

    # 当前在班用户id列表
    cur_user_id_list = []

    if morning or night:
        s_q = Q(date=cur_date)
        if morning and night:
            s_q &= (Q(morning=True)|Q(night=True))
        elif morning:
            s_q &= Q(morning=True)
        elif night:
            s_q &= Q(night=True)
        cur_user_id_list = list(BDTransferUserSchedule.objects.filter(s_q).values_list('user_id',flat=True))
    s_q = Q(is_f=True)
    if cur_user_id_list:
        s_q |= (Q(user_id__in=cur_user_id_list) & Q(is_active=True))

    # 当前在班 或者强制接收线索人员列表
    auto_assignor_object_list = BDTransferAutoAssignor.objects.filter(s_q)

    # 当前没有在班人员 也没有强制接收人员
    if not auto_assignor_object_list:
        message = u"当前无在班、强制接收线索人员！"
        return {'message':message,'code':1}

    # 当前在班 或者强制接收线索人员id列表
    available_user_id_list = []
    # 用户id对应ding
    user_id_2_ding = {}
    # 用户id对应用户姓名
    user_id_2_username = {}
    # 当前在班 人员 信息 列表
    now_auto_assignor_list = []
    # 当前强制接收线索 人员 信息 列表
    f_auto_assignor_list = []

    for single_item in auto_assignor_object_list:
        if single_item.user_id not in available_user_id_list:
            available_user_id_list.append(single_item.user_id)

        # 添加当前在班人员信息
        if single_item.user_id in cur_user_id_list:
            now_auto_assignor_list.append(
                {
                    'user_id': single_item.user_id,
                    'top': single_item.top,
                    'low': single_item.low
                }
            )
        # 添加强制接收线索人员信息
        if single_item.is_f:
            f_auto_assignor_list.append(
                {
                    'user_id': single_item.user_id,
                    'top': single_item.top,
                    'low': single_item.low
                }
            )
        # 添加 用户id对应ding账号
        user_id_2_ding[single_item.user_id] = single_item.ding
        # 添加 用户id对应用户username
        user_id_2_username[single_item.user_id] = single_item.user.username

    # 当前在班 或者强制接收线索人员 user_id : 当日分配数量
    user_id_2_count = {}
    # 当前在班 或者强制接收线索人员 user_id : rate
    user_id_2_rate = {}

    user_count_list = BDTransferAssignRecord.objects.filter(user_id__in=available_user_id_list, date=cur_date)
    for single_item in user_count_list:
        user_id_2_count[single_item.user_id] = single_item.count
    x_max = 0
    y_max = 0
    user_id_2_x_y = {}
    yestoday = cur_date + datetime.timedelta(days=-1)
    user_rate_list = TransferRate.objects.filter(date=yestoday)
    for single_item in user_rate_list:
        if not x_max:
            x_max = single_item.avg_30_inversion_rate
        else:
            if x_max < single_item.avg_30_inversion_rate:
                x_max = single_item.avg_30_inversion_rate
        if not y_max:
            y_max = single_item.avg_30_order_amount
        else:
            if y_max < single_item.avg_30_order_amount:
                y_max = single_item.avg_30_order_amount

        if int(single_item.consultant_id) in available_user_id_list:
            user_id_2_x_y[int(single_item.consultant_id)] = [single_item.avg_30_inversion_rate, single_item.avg_30_order_amount]

    for user_id in available_user_id_list:
        x = user_id_2_x_y.get(user_id,[0,0])[0]
        y = user_id_2_x_y.get(user_id,[0,0])[1]
        rate = ((x/x_max)*100)*0.7 + ((y/y_max)*100)*0.3
        user_id_2_rate[user_id] = rate

    # 当前在班人员最低转化率
    low_rate = 0
    # 当前在班人员最低转化率对应底限
    low_rate_low = 0

    # 更新当前在班人员的转化率
    for item in now_auto_assignor_list:
        item['rate'] = user_id_2_rate.get(item['user_id'],0)

    # 根据转化率排序
    now_auto_assignor_list.sort(key=lambda x:x['rate'],reverse=True)

    # 查找在班人员中 转化率最低人员 转化率、低限
    if now_auto_assignor_list:
        low_rate = now_auto_assignor_list[-1]['rate'] if now_auto_assignor_list[-1]['rate'] > 1 else 1
        low_rate_low = now_auto_assignor_list[-1]['low']

    # 分配阶段
    level = 1

    # 是否计算过 计算上限
    is_com = 0

    # 是否更新过强制接收线索人员 成单率
    is_f_com = 0

    # 用户id 对应分配的 线索id列表
    user_id_2_bdtransfer = {}

    while bdtransfer_id_list:
        # 每次循环后 算出任务id个数
        old_length = len(bdtransfer_id_list)
        if not cur_user_id_list:
            # 当前没有在班人员 直接进入阶段4
            level = 4

        if level == 1:
            # 第一阶段
            for single_assignor in now_auto_assignor_list:
                if not bdtransfer_id_list:
                    break
                cur_user_id = single_assignor['user_id']
                if user_id_2_count.setdefault(cur_user_id,0) < single_assignor['low']:
                    user_id_2_bdtransfer.setdefault(cur_user_id,[]).append(bdtransfer_id_list.pop())
                    user_id_2_count[cur_user_id] = user_id_2_count.setdefault(cur_user_id,0) + 1
            else:
                # 经过一轮分配后 没有分配出任务 进入第二阶段
                if old_length == len(bdtransfer_id_list):
                    level = 2

        elif level == 2:
            # 第二阶段

            # 判断是否计算过 计算上限
            if not is_com:
                for single_assignor in now_auto_assignor_list:
                    single_rate = single_assignor['rate'] if single_assignor['rate'] >1 else 1
                    com_top = round(single_rate/low_rate * low_rate_low)
                    single_assignor['com_top'] = com_top if com_top < single_assignor['top'] else single_assignor['top']
                is_com = 1

            for single_assignor in now_auto_assignor_list:
                if not bdtransfer_id_list:
                    break
                cur_user_id = single_assignor['user_id']

                if user_id_2_count[cur_user_id] < single_assignor['com_top']:
                    user_id_2_bdtransfer.setdefault(cur_user_id,[]).append(bdtransfer_id_list.pop())
                    user_id_2_count[cur_user_id] += 1
            else:
                # 经过一轮分配后 没有分配出任务 进入第三阶段
                if old_length == len(bdtransfer_id_list):
                    level = 3

        elif level == 3:
            # 第三阶段
            for single_assignor in now_auto_assignor_list:
                if not bdtransfer_id_list:
                    break
                cur_user_id = single_assignor['user_id']
                if user_id_2_count[cur_user_id] < single_assignor['top']:
                    user_id_2_bdtransfer.setdefault(cur_user_id, []).append(bdtransfer_id_list.pop())
                    user_id_2_count[cur_user_id] += 1
            else:
                if old_length == len(bdtransfer_id_list):
                    level = 4
        else:
            # 第四阶段
            # 没有强制接收线索人员 退出
            if not f_auto_assignor_list:
                break

            if not is_f_com:
                for single_assignor in f_auto_assignor_list:
                    single_assignor['rate'] = user_id_2_rate.get(single_assignor['user_id'],0)
                f_auto_assignor_list.sort(key=lambda x: x['rate'], reverse=True)

            for single_assignor in f_auto_assignor_list:
                if not bdtransfer_id_list:
                    break

                cur_user_id = single_assignor['user_id']
                user_id_2_bdtransfer.setdefault(cur_user_id, []).append(bdtransfer_id_list.pop())
                user_id_2_count[cur_user_id] = user_id_2_count.setdefault(cur_user_id,0) + 1
    # 分配成功人员 发送钉钉的手机号
    at_phone = []

    for user_id in user_id_2_bdtransfer:
        at_phone.append(user_id_2_ding[user_id])

    return {
        'message':message,
        'code':0,
        'last':bdtransfer_id_list,
        'assign':user_id_2_bdtransfer,
        'at_phone':at_phone,
        'user_id_2_username':user_id_2_username,
        'user_id_2_count':user_id_2_count
    }

#  公共池自动分发
@bind_context(uri_pre + 'auto_assign')
def auto_assign_mul_bdtransfer(ctx, bdtransfer_list):
    message = ''
    current_user_id = get_user_from_context(ctx).id
    bdtransfer_list = list(BDTransfer.objects.filter(id__in=bdtransfer_list, is_assign=False).order_by('-id').values_list('id',flat=True))
    if bdtransfer_list:
        bdtransfer_list = [str(item) for item in bdtransfer_list]
        res = auto_assign_single_bdtransfer(bdtransfer_list)
        if res['code']:
            return res
        else:
            if res['assign']:
                with transaction.atomic():
                    # 分配线索、更新分配数量、创建分配记录
                    for user_id in res['assign']:
                        username = res['user_id_2_username'][user_id]
                        bdtransfer_id_list = res['assign'][user_id]
                        BDTransfer.objects.filter(id__in=bdtransfer_id_list).update(**{'assigner':user_id,
                                                                                       'is_assign':True,
                                                                                       'current_follow_up_consultant_id':user_id,
                                                                                       'assigned_time':datetime.datetime.now(),
                                                                                       'pooled_time':datetime.datetime.now()})
                        record_list = []
                        for bdtransfer_id in bdtransfer_id_list:
                            record_list.append(BDTransferOperationRecord(**{
                                'bdtransfer_id':bdtransfer_id,
                                'operate_user_id':current_user_id,
                                'action':OPERATION_ACTION.ASSIGN,
                                'content':u'自动分配给{}'.format(username),

                            }))
                        if record_list:
                            BDTransferOperationRecord.objects.bulk_create(record_list)

                        if bdtransfer_id_list:
                            record = BDTransferAssignRecord.objects.filter(**{'user_id':user_id,'date':datetime.date.today()}).first()
                            if not record:
                                BDTransferAssignRecord.objects.create(**{'user_id':user_id,'date':datetime.date.today(),'count':len(bdtransfer_id_list)})
                            else:
                                record.count = record.count + len(bdtransfer_id_list)
                                record.save(update_fields=['count'])
                # 发送钉钉消息
                try:
                    ding_result =send_notify(res['assign'], res['user_id_2_username'] , res['at_phone'])
                except:
                    message = '发送钉钉消息失败！\n'
                    logging_exception()

            user_id_2_username = res['user_id_2_username']
            assign = res['assign']
            for assign_user in assign:
                message += '线索: ' + ','.join(assign[assign_user]) + '---' + user_id_2_username.get(assign_user,'') + '---成功\n'
            last = res['last']
            if last:
                message += '线索: ' + ','.join(last) + '---分配失败;'

            return {'code':0, 'message':message}
    else:
        return {'code':1, 'message':'没有可以分发的线索'}