# -*- coding: UTF-8 -*-
from __future__ import division
import datetime
import traceback
from django.conf import settings

from django.db.models import Sum
from celery import shared_task
from gm_types.doctor import BUDAN_LURU_STATUS, BUDAN_LURU_TYPE
from gm_types.gaia import ORDER_STATUS
from api.models import Order, BuDanLuRu, ConversationUserStatus, MerchantRelevance, Conversation
from hera.management.commands.utils import get_mail
from hippo.models import Doctor, Merchant, MerchantPvStat
from hippo.models.user_list import UserList
from hippo.tool.merchant_tool import update_merchant_doctor_relation
from maidan.models import MaidanOrder
from helios.rpc.internal.default_invoker import create_default_invoker
from django.core.cache import cache
from django.conf import settings
import redis
@shared_task
def update_merchant_by_doctor(doctor_ids):
    for doctor in Doctor.objects.filter(id__in=doctor_ids):
        update_merchant_doctor_relation(doctor)

@shared_task
def update_merchant_level(end_days=0, start_days=0, month=3):
    today = datetime.date.today()
    end_time = datetime.datetime(today.year, today.month, today.day - end_days, 0, 0, 0)
    start_time = datetime.datetime(end_time.year, end_time.month - month, end_time.day - start_days, 0, 0, 0)
    data = Merchant.objects.all()
    doctor_ids = {}
    # 获取所有医生的id
    for i in data:
        key = i.id
        val = list(i.merchant_doctors.all().values_list('doctor_id'))
        doctor_ids_set = set()
        for item in val:
            doctor_ids_set.add(item[0])
        doctor_ids[key] = list(doctor_ids_set)
        # 计算订单，买单，补单GMV
        # #订单
        res_dict = Order.objects.filter(service__doctor_id__in=doctor_ids_set, validate_time__gte=start_time,
                                        validate_time__lte=end_time, validated=True).aggregate(sum=Sum("service_price"))
        order_sum = res_dict.get("sum") if res_dict.get("sum") else 0.00
        # 买单
        res_dict = MaidanOrder.objects.filter(doctor_id__in=doctor_ids_set, payment_time__gte=start_time,
                                              payment_time__lte=end_time, status=ORDER_STATUS.SETTLED).aggregate(sum=Sum("maidan_price_cent"))
        maidan_sum = res_dict.get("sum")/100 if res_dict.get("sum") else 0.00
        # 补单录入
        res_dict = BuDanLuRu.objects.filter(doctor_id__in=doctor_ids_set, created_time__gte=start_time,
                                              created_time__lte=end_time, status=BUDAN_LURU_STATUS.ENTERED, type=BUDAN_LURU_TYPE.COMMON).aggregate(sum=Sum("amount"))
        budanluru_sum = res_dict.get("sum")*10 if res_dict.get("sum") else 0.00
        i.verify_gmv_score = (order_sum + maidan_sum + budanluru_sum) / (10000.0 * month)
    # 按医生的维度获取GMV以及广告消耗
    # 初始化rpc对像
    invoker = create_default_invoker(debug=settings.DEBUG)
    rpc_client = invoker['artemis/account/accountflow/sum'](doctor_ids=doctor_ids,
                                                            start_time=start_time.strftime('%Y-%m-%d %H:%M:%S'),
                                                            end_time=end_time.strftime('%Y-%m-%d %H:%M:%S'))
    result = rpc_client.unwrap()
    # 更新商户的评级
    for i in data:
        i.advertise_score = result.get(str(i.id)) / (10000.0 * month)
        i.merchant_score = i.verify_gmv_score * 0.6 + i.advertise_score * 0.4
        if i.merchant_score > 72:
            i.merchant_level = 0
        elif i.merchant_score > 36:
            i.merchant_level = 1
        elif i.merchant_score > 22:
            i.merchant_level = 2
        elif i.merchant_score > 7:
            i.merchant_level = 3
        elif i.merchant_score > 1:
            i.merchant_level = 4
        else:
            i.merchant_level = 5
        i.save()


@shared_task
def user_list_data_write():
    #获取所有商户
    merchants = Merchant.objects.all()
    """
    获取单个商户所对应的所有用户,下单同时产生私信，私信用户包含下单、支付和验证的用户
    通过私信维度筛选用户，后再更新订单信息
    """
    for merchant in merchants:
        try:
            print(merchant.id)
            """
            #获取当前商户下的所有doctor_id,
            doctor_list_ids=[(u'zhangweixin',)]
            """
            doctor_ids = []
            doctor_list_ids = merchant.merchant_doctors.all().values_list('doctor_id')
            for item in doctor_list_ids:
                doctor_ids.append(item[0])
            """
            通过医生的doctor_id获取其对应的doctor_user_id
            在conversationuserstatus表中通过医生的用户id获取本商户的所有私信
            """
            doctor_list_user_ids = Doctor.objects.filter(id__in=doctor_ids).values_list('user_id')
            doctor_user_ids = []
            for item in doctor_list_user_ids:
                doctor_user_ids.append(item[0])
            conversationuserstatus_list = ConversationUserStatus.objects.filter(user_id__in=doctor_user_ids).order_by('conversation__created_time')

            """
            通过商户的私信或对应的会话，通过会话获取会话对应的另一个user_id
            并将用户写入user_list
            """
            for conversationuserstatus in conversationuserstatus_list:
                doctor_user_id = conversationuserstatus.user_id
                user_list = conversationuserstatus.conversation.user_status_set.values_list('user_id')
                for item in user_list:
                    if doctor_user_id != item[0]:
                        user_id = item[0]
                        break
                defaults = {'conversation_id': conversationuserstatus.conversation_id, 'doctor_user_id': doctor_user_id,
                            'conversation_created_time': conversationuserstatus.conversation.created_time}
                kwargs = {'merchant_id': merchant.id, 'user_id': user_id}
                user_obj, _ = UserList.objects.update_or_create(defaults=defaults, **kwargs)
                """
                在MerchantPvStat表中获取用户最近浏览的记录
                """
                time_now = datetime.datetime.today()
                start_time = time_now - datetime.timedelta(days=30)
                browse_obj = MerchantPvStat.objects.filter(user_id=user_id, merchant_id=merchant.id, browsing_time__gte=start_time).order_by('browsing_time').last()
                if browse_obj:
                    user_obj.browse_id = browse_obj.id
                    user_obj.browse_time = browse_obj.browsing_time
                """
                更新用户的订单相关信息
                支付订单
                认证订单
                """
                pay_order = Order.objects.filter(user_id=user_obj.user_id, service__doctor_id__in=doctor_ids, status=ORDER_STATUS.PAID).order_by('pay_time').last()
                if pay_order:
                    user_obj.order_pay_id = pay_order.id
                    user_obj.order_pay_time = pay_order.pay_time
                validated_orders = Order.objects.filter(user_id=user_obj.user_id, service__doctor_id__in=doctor_ids, validated=True).order_by('validate_time')
                if validated_orders:
                    res = validated_orders.aggregate(sum=Sum("real_payment"))
                    user_obj.amount = res.get("sum") if res.get("sum") else 0.00
                    user_obj.order_validated_time = validated_orders.last().validate_time
                    user_obj.order_validated_id = validated_orders.last().id
                user_obj.modify_time = datetime.datetime.today()
                user_obj.save()
        except:
            try:
                info = str(traceback.format_exc())
                sub = '用户列表数据写入错误统计.txt'
                body = '用户列表数据写入错误统计'
                to_user_email = 'songzhenqi@igengmei.com'
                message = info + str(merchant.id)
                get_mail(sub, body, to_user_email, message).send()
                continue
            except:
                continue




@shared_task
def message_sync(conversation, send_user, target_user):
    """
    :param conversation:
    :param id:
    :return:
    判断目标是不是医生
    不是：结束
    是：userlist更新或者其他操作
    """
    doctor = Doctor.objects.filter(user_id=target_user.id).first()
    if not doctor:
        return None
    """
    判断该用户是不是第一次和会话医生所属的商户第一次私信沟通
    """
    merchant = MerchantRelevance.objects.filter(doctor_id=doctor.id).first()
    if not merchant:
        return None
    doctor_list_ids = MerchantRelevance.objects.filter(merchant_id=merchant.merchant_id).values_list('doctor_id')
    doctor_ids = []
    for item in doctor_list_ids:
        doctor_ids.append(item[0])
    user_list_ids = Doctor.objects.filter(id__in=doctor_ids).values_list('user_id')
    user_ids = []
    for item in user_list_ids:
        user_ids.append(item[0])
    conversation_amount = 0
    for user_id in user_ids:
        hash_user_id = Conversation.gen_uid_hash([int(send_user.id), int(user_id)])
        count = Conversation.objects.filter(uid_hash=hash_user_id).count()
        conversation_amount += count
        if conversation_amount > 1:
            return '已存在用户'
    """
    该用户第一次与该商户下的医生私信会话
    将用户写入userlist,在ConversationUserStatus中找到此次会话的医生方
    """

    defaults = {'conversation_id': conversation.id, 'doctor_user_id': target_user.id,
                'conversation_created_time': conversation.created_time}
    kwargs = {'merchant_id': merchant.merchant_id, 'user_id': send_user.id}
    user_obj, _ = UserList.objects.update_or_create(defaults=defaults, **kwargs)
    """
    在MerchantPvStat表中获取用户最近浏览的记录
    """
    time_now = datetime.datetime.today()
    start_time = time_now - datetime.timedelta(days=30)
    browse_obj = MerchantPvStat.objects.filter(user_id=send_user.id, merchant_id=merchant.merchant_id, browsing_time__gte=start_time).order_by('browsing_time').last()
    if browse_obj:
        user_obj.browse_id = browse_obj.id
        user_obj.browse_time = browse_obj.browsing_time
    """
    更新用户的订单相关信息
    支付订单
    认证订单
    """
    pay_order = Order.objects.filter(user_id=user_obj.user_id, service__doctor_id__in=doctor_ids,
                                     status=ORDER_STATUS.PAID).order_by('pay_time').last()
    if pay_order:
        user_obj.order_pay_id = pay_order.id
        user_obj.order_pay_time = pay_order.pay_time
    validated_orders = Order.objects.filter(user_id=user_obj.user_id, service__doctor_id__in=doctor_ids,
                                            validated=True).order_by('validate_time')
    if validated_orders:
        user_obj.order_validated_id = validated_orders.last().id
        user_obj.order_validated_time = validated_orders.last().validate_time
        res = validated_orders.aggregate(sum=Sum("real_payment"))
        user_obj.amount = res.get("sum") if res.get("sum") else 0.00
    user_obj.modify_time = datetime.datetime.today()
    user_obj.save()



@shared_task
def userlist_update_pay_order_per_hour():
    """
    支付订单记录更新
    :return:
    """
    """
    通过pay_time更新用户最新支付订单
    """
    doctor_cache = redis.StrictRedis(**settings.REDIS['doctor'])
    end_time = datetime.datetime.today()
    expire_time = end_time + datetime.timedelta(hours=2)
    if not doctor_cache.setnx('userlist_update_pay_order_per_hour_lock', expire_time.strftime('%Y-%m-%d %H:%M:%S')):
        redis_expire_time_str = doctor_cache.get('userlist_update_pay_order_per_hour_lock')
        redis_expire_time = datetime.datetime.strptime(redis_expire_time_str, '%Y-%m-%d %H:%M:%S')
        if end_time > redis_expire_time:
            doctor_cache.set('userlist_update_pay_order_per_hour_lock', expire_time.strftime('%Y-%m-%d %H:%M:%S'))
        else:
            return None
    pay_order_start_time = doctor_cache.get('pay_order_start_time')
    if not pay_order_start_time:
        # if UserList.objects.all().exclude(order_pay_time=None).order_by('order_pay_time').first():
        #     pay_order_start_time = UserList.objects.all().exclude(order_pay_time=None).order_by('order_pay_time').first().order_pay_time
        # else:
        pay_order_start_time = datetime.datetime.strptime('2019-09-09 00:00:00', '%Y-%m-%d %H:%M:%S')
    pay_orders = Order.objects.filter(pay_time__gt=pay_order_start_time, pay_time__lte=end_time, status=ORDER_STATUS.PAID).order_by('pay_time')
    for pay_order in pay_orders:
        print(pay_order.id)
        if UserList.objects.filter(order_pay_id=pay_order.id):
            continue
        """
        判断当前订单归属：1、新用户的订单，2、已有用户的历史订单，3、已有用户的新订单
        """
        user_id = pay_order.user_id
        pay_time = pay_order.pay_time
        doctor_id = pay_order.service.doctor_id
        # doctor_user_id = Doctor.objects.get(id=doctor_id).user_id
        merchantrelevance = MerchantRelevance.objects.filter(doctor_id=doctor_id).first()
        if merchantrelevance:
            merchant_id = merchantrelevance.merchant_id
        else:
            continue
        obj = UserList.objects.filter(user_id=user_id, merchant_id=merchant_id).first()
        if obj:
            if not obj.order_pay_time or obj.order_pay_time < pay_time:
                obj.order_pay_time = pay_time
                obj.order_pay_id = pay_order.id
                # obj.doctor_user_id = doctor_user_id
                obj.save()
        else:
            defaults = {'order_pay_time':pay_time,'order_pay_id':pay_order.id,'modify_time':datetime.datetime.today()}
            kwargs = {'merchant_id': merchant_id, 'user_id': user_id}
            UserList.objects.update_or_create(defaults=defaults, **kwargs)
    doctor_cache.set('pay_order_start_time', end_time)
    doctor_cache.delete('userlist_update_pay_order_per_hour_lock')

@shared_task
def userlist_update_validate_order_per_hour():
    """
    通过validate_time更新用户最新验证订单
    """
    end_time = datetime.datetime.today()
    doctor_cache = redis.StrictRedis(**settings.REDIS['doctor'])
    expire_time = end_time + datetime.timedelta(hours=2)
    if not doctor_cache.setnx('userlist_update_validate_order_per_hour_lock', expire_time.strftime('%Y-%m-%d %H:%M:%S')):
        redis_expire_time_str = doctor_cache.get('userlist_update_validate_order_per_hour_lock')
        redis_expire_time = datetime.datetime.strptime(redis_expire_time_str, '%Y-%m-%d %H:%M:%S')
        if end_time > redis_expire_time:
            doctor_cache.set('userlist_update_validate_order_per_hour_lock', expire_time.strftime('%Y-%m-%d %H:%M:%S'))
        else:
            return None
    validate_order_start_time = doctor_cache.get('validate_order_start_time')
    if not validate_order_start_time:
        # if UserList.objects.all().exclude(order_validated_time=None).order_by('order_validated_time').first():
        #     validate_order_start_time = UserList.objects.all().exclude(order_validated_time=None).order_by('order_validated_time').first().order_validated_time
        # else:
        validate_order_start_time = datetime.datetime.strptime('2019-09-09 00:00:00', '%Y-%m-%d %H:%M:%S')
    validate_orders = Order.objects.filter(validate_time__gt=validate_order_start_time, validate_time__lte=end_time, validated=True).order_by('validate_time')
    for validate_order in validate_orders:
        print(validate_order.id)
        if UserList.objects.filter(order_validated_id=validate_order.id):
            continue
        """
        获取当前验证订单的用户id，商户id，验证时间，
        """
        user_id = validate_order.user_id
        validate_time = validate_order.validate_time
        doctor_id = validate_order.service.doctor_id
        merchantrelevance = MerchantRelevance.objects.filter(doctor_id=doctor_id).first()
        if merchantrelevance:
            merchant_id = merchantrelevance.merchant_id
        else:
            continue
        """
        判断当前验证订单归属：1、新用户的订单，2、已有用户的历史订单，3、已有用户的新订单
        """
        obj = UserList.objects.filter(user_id=user_id, merchant_id=merchant_id).first()
        if obj:
            if not obj.order_validated_time  or obj.order_validated_time < validate_time:
                obj.order_validated_time = validate_time
                obj.order_validated_id = validate_order.id
                obj.amount += validate_order.real_payment
                obj.save()
        else:

            defaults = {'order_validated_time':validate_time, 'order_validated_id':validate_order.id, 'modify_time':datetime.datetime.today()}
            kwargs = {'merchant_id': merchant_id, 'user_id': user_id}
            user_obj, _ = UserList.objects.update_or_create(defaults=defaults, **kwargs)
            """
            更新用户的验证金额
            """
            user_obj.amount = validate_order.real_payment
            user_obj.save()

    doctor_cache.set('validate_order_start_time', end_time)
    doctor_cache.delete('userlist_update_validate_order_per_hour_lock')

@shared_task
def userlist_update_conversation_per_hour():
    """
    通过conversation_id更新用户最新私信
    """
    doctor_cache = redis.StrictRedis(**settings.REDIS['doctor'])
    end_time = datetime.datetime.today()
    expire_time = end_time + datetime.timedelta(hours=2)
    if not doctor_cache.setnx('userlist_update_conversation_per_hour_lock', expire_time.strftime('%Y-%m-%d %H:%M:%S')):
        redis_expire_time_str = doctor_cache.get('userlist_update_conversation_per_hour_lock')
        redis_expire_time = datetime.datetime.strptime(redis_expire_time_str, '%Y-%m-%d %H:%M:%S')
        if end_time > redis_expire_time:
            doctor_cache.set('userlist_update_conversation_per_hour_lock', expire_time.strftime('%Y-%m-%d %H:%M:%S'))
        else:
            return None
    conversation_start_id = doctor_cache.get('conversation_start_id')
    if not conversation_start_id:
        # if UserList.objects.all().exclude(conversation_id=None).order_by('conversation_id').first():
        #     conversation_start_id = UserList.objects.all().exclude(conversation_id=None).order_by('conversation_id').first().conversation_id
        # else:
        #     conversation_start_id = 0
        conversation_start_time = datetime.datetime.strptime('2019-09-09 00:00:00', '%Y-%m-%d %H:%M:%S')
        conversations = Conversation.objects.filter(created_time__gte=conversation_start_time).order_by('id')
    else:
        conversations = Conversation.objects.filter(id__gt=conversation_start_id).order_by('id')

    for conversation in conversations:
        """
        通过订单所属的商户号和user_id在userlist表中匹配
        """
        print(conversation.id)
        if UserList.objects.filter(conversation_id=conversation.id):
            continue
        user_list = conversation.user_status_set.values_list('user_id')
        """
        分别获取医生和用户的user_id
        """
        doctor_user_id = user_id = None
        for item in user_list:
            if Doctor.objects.filter(user_id=item[0]):
                doctor_user_id = item[0]
            else:
                user_id = item[0]
        if not doctor_user_id or not user_id:
            continue
        doctor_id = Doctor.objects.get(user_id=doctor_user_id).id
        merchantrelevance = MerchantRelevance.objects.filter(doctor_id=doctor_id).first()
        if merchantrelevance:
            merchant_id = merchantrelevance.merchant_id
        else:
            continue
        """
        判断当前私信归属：1、新用户的私信，2、已有用户的旧私信，3、已有用户的新私信
        """
        obj = UserList.objects.filter(user_id=user_id, merchant_id=merchant_id).first()
        if obj:
            if obj.conversation_id < conversation.id:
                obj.conversation_id = conversation.id
                obj.conversation_created_time = conversation.created_time
                obj.doctor_user_id = doctor_user_id
                obj.save()
        else:
            defaults = {'doctor_user_id': doctor_user_id,'conversation_id':conversation.id,'conversation_created_time':conversation.created_time,'modify_time':datetime.datetime.today()}
            kwargs = {'merchant_id': merchant_id, 'user_id': user_id}
            UserList.objects.update_or_create(defaults=defaults, **kwargs)
    if conversations:
        doctor_cache.set('conversation_start_id', conversations.last().id)
    doctor_cache.delete('userlist_update_conversation_per_hour_lock')


@shared_task
def userlist_update_browse_per_hour():
    """
    通过browse_id更新用户30天内最新浏览记录
    """
    doctor_cache = redis.StrictRedis(**settings.REDIS['doctor'])
    end_time = datetime.datetime.today()
    expire_time = end_time + datetime.timedelta(hours=2)
    if not doctor_cache.setnx('userlist_update_browse_per_hour_lock', expire_time.strftime('%Y-%m-%d %H:%M:%S')):
        redis_expire_time_str = doctor_cache.get('userlist_update_browse_per_hour_lock')
        redis_expire_time = datetime.datetime.strptime(redis_expire_time_str, '%Y-%m-%d %H:%M:%S')
        if end_time > redis_expire_time:
            doctor_cache.set('userlist_update_browse_per_hour_lock', expire_time.strftime('%Y-%m-%d %H:%M:%S'))
        else:
            return None
    browse_start_id = doctor_cache.get('browse_start_id')
    if not browse_start_id:
        # if UserList.objects.all().exclude(browse_time=None).order_by('browse_id').first():
        #     browse_start_id = UserList.objects.all().exclude(browse_time=None).order_by('browse_id').first().browse_id
        # else:
        #     browse_start_id = 0
        browsing_start_time = datetime.datetime.strptime('2019-09-18 11:00:00', '%Y-%m-%d %H:%M:%S')
        browses = MerchantPvStat.objects.filter(browsing_time__gte=browsing_start_time).order_by('id')
    else:
        browses = MerchantPvStat.objects.filter(id__gt=browse_start_id).order_by('id')

    for browse in browses:
        """
        通过订单所属的merchant_id和user_id在userlist表中匹配
        """
        print(browse.id)
        # if UserList.objects.filter(browse_id=browse.id):
        #     continue
        user_id = browse.user_id
        merchant_id = browse.merchant_id
        """
        判断当前浏览记录归属：1、已有用户的历史浏览记录，2、已有用户的新浏览记录
        """
        obj = UserList.objects.filter(user_id=user_id,merchant_id=merchant_id).first()
        if obj:
            if obj.browse_id < browse.id:
                obj.browse_id = browse.id
                obj.browse_time = browse.browsing_time
                obj.save()
    """
    清除最新浏览记录在30天以前数据
    """
    end_time = datetime.datetime.today()-datetime.timedelta(days=30)
    users = UserList.objects.filter(browse_time__lt=end_time)
    if users:
        users.update(browse_id=None, browse_time=None, modify_time=datetime.datetime.today())
    if browses:
        doctor_cache.set('browse_start_id', browses.last().id)
    doctor_cache.delete('userlist_update_browse_per_hour_lock')
