# coding:utf-8

from __future__ import unicode_literals

import dateutil.parser as parser
import time
import datetime

from api.models import Merchant, Coupon, GiftToCoupon

from django.core.management import BaseCommand
from rpc.tool.error_code import CODES

from search.utils.conversation import search_conversation_from_es
from services.unread.stat import UserUnread

from api.models.types import MESSAGE_TYPE
from hippo.models import MerchantRelevance, Doctor
from gm_types.gaia import DOCTOR_TYPE, COUPON_TYPES, COUPON_DISTRIBUTION_STATUS
from gm_types.msg import CONVERSATION_ORDER, CONVERSATION_TYPE
from gm_types.trade import COUPON_TIME_TYPE
from message.views.message import internal_message_send
from api.models.message import ConversationUserStatus

from rpc.exceptions import RPCPermanentError


def get_conversations_v3(user_ids, offset, size, order_by=CONVERSATION_ORDER.LAST_REPLY_TIME,
                         last_reply_time_start=None, last_reply_time_end=None, reply_status=None,
                         is_star=None, user_id=None, user_last_name=None, comment=None):
    """
    获取会话列表， 与v2不同的是全部走es获取conversation_ids
    :param user_ids: LIST[USER_ID]
    :param offset: INT 偏移量
    :param size: INT 每页数量
    :param order_by: 排序规则
    :param last_reply_time_start: str 最后回复开始时间筛选
    :param last_reply_time_end: str 最后回复结束时间筛选
    :param reply_status: bool 回复状态（新消息、旧消息）
    :param is_star: bool
    :param user_id: int 精确搜索用户ID
    :param user_last_name: int 搜索用户昵称
    :param comment: int 搜索备注
    :return:
    """
    if not isinstance(user_ids, list):
        raise RPCPermanentError
    if not isinstance(size, int):
        raise RPCPermanentError
    if size <= 0 or size >= 50:
        size = 50
    es_filters = {'user_ids': user_ids}
    if is_star is not None and isinstance(is_star, bool):
        es_filters['is_star'] = is_star
    if last_reply_time_start is not None:
        es_filters['last_reply_time_start_gte'] = parser.parse('{}+0800'.format(last_reply_time_start)).isoformat()
    if last_reply_time_end is not None:
        es_filters['last_reply_time_end_lte'] = parser.parse('{}+0800'.format(last_reply_time_end)).isoformat()
    es_query = dict()
    # if search_content is not None:
    #     es_query = {
    #         'comment': search_content,
    #         'user_last_name': search_content,
    #     }
    if user_id is not None:
        es_query['user_id'] = user_id
    if user_last_name:
        es_query['user_last_name'] = user_last_name
    if comment:
        es_query['comment'] = comment
    es_sort_type = order_by
    # 全部
    es_result_total = search_conversation_from_es(offset=offset, size=size, filters=es_filters,
                                                  query=es_query, sort_type=es_sort_type)
    # 已回复
    es_filters['multi_filter_status'] = {
        'status': True,
        'user_ids': user_ids,
    }
    es_result_reply = search_conversation_from_es(offset=offset, size=size, filters=es_filters,
                                                  query=es_query, sort_type=es_sort_type)
    # 未回复
    es_filters['multi_filter_status'] = {
        'status': False,
        'user_ids': user_ids,
    }
    es_result_not_reply = search_conversation_from_es(offset=offset, size=size, filters=es_filters,
                                                      query=es_query, sort_type=es_sort_type)
    # es_result = search_conversation_from_es(offset=offset, size=size, filters=es_filters,
    #                                         query=es_query, sort_type=es_sort_type)
    if reply_status == None:
        es_result = es_result_total
    else:
        if reply_status:
            es_result = es_result_reply
        else:
            es_result = es_result_not_reply
    _conversation_ids = es_result['conversation_ids']
    cus_ids = []
    for conversation_id in _conversation_ids:
        sub_ids = ConversationUserStatus.objects.filter(
            user_id__in=user_ids, conversation_id=conversation_id
        ).values_list('id', flat=True)
        cus_ids.extend(list(sub_ids))
    conversation_user_status = ConversationUserStatus.objects.filter(id__in=cus_ids).order_by('-last_reply_time')

    conversation_info_list = [cs.conversation.conversation_info_v3(cs, user_ids) for cs in conversation_user_status]
    conversation_id_to_user_id = {cs.conversation_id: cs.user_id for cs in conversation_user_status}
    for c in conversation_info_list:
        default = 1 if c['is_new'] else 0
        c['unread_num'] = UserUnread(conversation_id_to_user_id[c['id']]
                                     ).get_conversation_unread(c['id'], default=default)
    return {
        'conversation_list': conversation_info_list,
        'total_count': es_result_total['total_count'],
        'reply_total': es_result_reply['total_count'],
        'not_reply_total': es_result_not_reply['total_count']
    }


class Command(BaseCommand):
    DOCTOR_BUSINESS_CHANNAL_ID_ONLINE = 35

    # only check merchant id can use
    availableMerchantIDList = []

    # check merchant id and coupon can use
    availableMerchantIDListWithCoupon = []

    onlineTestuid = 33703995

    # content = [["area", "merchant_name", 6477328345687146383, 533, 0, "福建最大的整形机构在线独家补贴，领取红包为美减压，爱美就到爱美尔"]]

    c = [
        ["华东", "杭州大麦整形外科门诊部", 6417270138088734617, 61092, 0, "感谢宝贝的关注 大麦微针植发.特惠活动\"植男\"\"植女\"变形记来啦下单预约可享受 到院术后深层理疗2次免费试种200单位 【无痕种植发际线 仅4800元/1000单位】【大麦专利微针技术 8800元/1000单位】【PSE微针分层剃发技术:1000单位限时抢购9900元】【PTT微针加密技术:1000单位限时抢购12800元】\【完全不剃发:500单位限时抢购9999元】【种植眉毛:限时抢购双侧部位12798元】更有10000-500元红包等你来领！历史超低价低到没朋友~ 快来下单囤货吧??~错过等一年！ 宝宝快快下单预约吧~~"],
        ["华东", "上海光博士医疗美容门诊部", 6328834508275693538, 60590, 60591,
         "光博士品质服务 八月钜惠：1.国产除皱20单位 198元 2.光子嫩肤闲时卡 199元 3.皮秒嫩肤+C6祛黄 399元 4.M22光子嫩肤399元 5.私密漂红 380元 6.水光2次+C62次 666元 7.切开双眼皮 980元 8.基础水光年卡1080元 9.蜂巢皮秒全面部 1200元 10.菲蜜丽私密紧致 1280元 11.伊婉V玻尿酸 1480元 12.热拉提全面部 1980元 13.自体脂肪隆胸 4900元 14.乔雅登雅致 3980元 15.热玛吉全面部 5999元 光博士始终坚持品质医美 放心医美 现有常驻医生8位 两位副高 四位主治 医院逾4000平  大国匠心值得信赖"],
        ["华东", "江苏施尔美整形美容医院", 6328834446480980730, 60600, 0,
         "感谢小主关注江苏施尔美，送您新人入门礼"],
        ["华东", "上海天大医疗美容医院", 6328834467477712267, 61091, 0,
         "上海天大整形，8月欢乐购 ①无针水光（8月特惠）51元 ②深蓝射频眼周         299元 ③热拉提PLUS           999元 ④芭比眼综合案例享      4800元 ⑤进口假体隆鼻案例享    3888元 ⑥双美胶原蛋白0.5ml     2680元 ⑦热玛吉闺密双人行       7900元/人 更多活动详情请咨询客服宝宝~~"],
        ["华西", "重庆万家燕整形", 6329570617217561931, 60323, 0,
         "感谢关注重庆万家燕整形外科医院，本院是西南地区首家三级整形外科医院，四级高难度手术合法资质，硕导专家团队&金燕体系&路费报销，最高抵扣2500，期待您的来访！"]
    ]

    def handle(self, *args, **options):
        self.checkMerchant()
        self.checkCoupon()

        self.sendCoupon()

    def sendCoupon(self):

        resMerchantFailedSend = {}
        resMerchantSucceedSend = {}
        resConversationMap = {}

        sendReqNum = 0
        timeStart = time.time()

        for line in self.availableMerchantIDListWithCoupon:

            failedSendUserList = []
            succeedSendUserList = []
            allConversationID = []

            doctorIDList = []
            doctorUIDList = []
            sendCouponAdminUID = 0
            targetUserSet = set()
            sendCouponList = []
            conversationList = []

            merchantID = line[2]

            print()
            print()
            print("start send coupon of merchant id: {merchantID}".format(merchantID=merchantID))
            print("merchant id: ", merchantID)
            couponID1 = line[3]
            print("coupon id 1: ", couponID1)
            couponID2 = line[4]
            print("coupon id 2: ", couponID2)
            sendCouponList.append(couponID1)
            sendCouponList.append(couponID2)

            sendGiftList = self.getGiftID(sendCouponList)
            print "gift list: "
            print sendGiftList
            msgContent = line[5]
            print("msg content: ", msgContent)

            # get merchant info
            merchant = Merchant.objects.filter(id=merchantID).first()
            if not merchant:
                continue

            # get admin doctor id
            adminDoctorID = merchant.doctor.id

            # add admin doctor id to doctorIDList
            doctorIDList.append(adminDoctorID)

            # get other doctors
            doctors = MerchantRelevance.objects.filter(merchant_id=merchantID, doctor__doctor_type=DOCTOR_TYPE.DOCTOR)
            doctorCount = doctors.count()
            ds = doctors[0: doctorCount]
            otherDoctorList = [d.doctor.id for d in ds]

            # add other doctor id to doctorIDList
            doctorIDList.extend(otherDoctorList)

            # get all doctor info
            doctors = Doctor.objects.filter(pk__in=doctorIDList)

            for doctor in doctors:

                ddid = doctor.id
                duid = doctor.user_id

                # add every doctor uid to doctorUIDList
                doctorUIDList.append(duid)
                if ddid == adminDoctorID:
                    sendCouponAdminUID = duid

            # get message target user' user_id list at 2020/4/1 - 2020/7/31
            offsetNumber = 0
            while True:

                # get conversations between 2020/4/1 -- 2020/6/30 of merchant
                conversationResList = get_conversations_v3(
                    user_ids=doctorUIDList,
                    offset=offsetNumber,
                    size=50,
                    is_star=0,
                    last_reply_time_start="2020-01-01T00:00:00",
                    last_reply_time_end="2020-03-01T00:00:00",
                )

                # print("msg res: ")
                # pprint.pprint(conversationResList)
                resCount = conversationResList["total_count"]

                # no conversation
                if resCount <= 0:
                    break

                conversationListOne = conversationResList["conversation_list"]

                conversationList.extend(conversationListOne)

                if len(conversationListOne) < 50:
                    break

                offsetNumber += 50

            conversationNum = len(conversationList)
            print("conversation number of merchant: {merchantID} in 2020-1-1 and 2020-3-31 is ".format(
                merchantID=merchantID), conversationNum)

            # no conversation, handle next merchant
            if conversationNum == 0:
                continue

            # get target user id set
            # 因为发送者和接收者，顺序不定，所以都取出来去判断
            for conversationRow in conversationList:

                targetUserID0 = conversationRow["user_ids"][0]
                targetUserID1 = conversationRow["user_ids"][1]
                conversationID = conversationRow["id"]

                allConversationID.append(conversationID)

                if targetUserID0 not in doctorUIDList:
                    targetUserSet.add(targetUserID0)

                if targetUserID1 not in doctorUIDList:
                    targetUserSet.add(targetUserID1)

            # print("target user id set: ", targetUserSet)
            targetUserNum = len(targetUserSet)
            print("target user number of merchant id:{merchantID} is ".format(merchantID=merchantID), targetUserNum)

            targetUserSet.add(self.onlineTestuid)

            for targetUserOne in targetUserSet:

                for giftID in sendGiftList:

                    resSendCoupon = internal_message_send(
                        sender_user_id=sendCouponAdminUID,
                        target_user_id=targetUserOne,
                        msg_type=MESSAGE_TYPE.GIFT,
                        conversation_type=CONVERSATION_TYPE.MESSAGE,
                        content={"gift_id": giftID, "channel_id": self.DOCTOR_BUSINESS_CHANNAL_ID_ONLINE}
                    )

                    sendReqNum += 1

                    errSendGift = resSendCoupon["error"]
                    # send failed
                    if errSendGift == CODES.MESSAGE_CONTENT_FILTERED_OUT:
                        # print(
                        #     "Failed to send merchant:{merchantID}'s coupon: {couponGiftID} to user: {targetIDOne}".format(
                        #         merchantID=merchantID, couponGiftID=giftID, targetIDOne=targetUserOne))

                        failedGiftInfo = str(giftID) + "_" + str(targetUserOne)
                        failedSendUserList.append(failedGiftInfo)

                    # send success
                    # if errSendGift == CODES.SUCCESS:
                    #     print(
                    #         "Succeed to send merchant:{merchantID}'s coupon: {couponGiftID} to user: {targetIDOne}".format(
                    #             merchantID=merchantID, couponGiftID=giftID, targetIDOne=targetUserOne))

                # send msg
                resSendMsg = internal_message_send(
                    sender_user_id=sendCouponAdminUID,
                    target_user_id=targetUserOne,
                    msg_type=MESSAGE_TYPE.TEXT,
                    conversation_type=CONVERSATION_TYPE.MESSAGE,
                    content={"text": msgContent}
                )

                sendReqNum += 1

                errSendMsg = resSendMsg["error"]
                # if errSendMsg == CODES.MESSAGE_CONTENT_FILTERED_OUT:
                #     print(
                #         "Failed to send merchant:{merchantID}'s msg to user: {targetIDOne}".format(
                #             merchantID=merchantID, targetIDOne=targetUserOne))

                if errSendMsg == CODES.SUCCESS:
                    # print(
                    #     "Succeed to send merchant:{merchantID}'s msg to user: {targetIDOne}".format(
                    #         merchantID=merchantID, targetIDOne=targetUserOne))
                    succeedSendUserList.append(targetUserOne)

            resMerchantFailedSend[merchantID] = failedSendUserList
            resConversationMap[merchantID] = allConversationID
            resMerchantSucceedSend[merchantID] = succeedSendUserList

            print("send coupon complete of merchant: {merchantID}".format(merchantID=merchantID))

        print("res failed to send: ")
        print(resMerchantFailedSend)

        print("res succeed to send: ")
        print(resMerchantSucceedSend)

        print("conversation id list: ")
        print(resConversationMap)

        print("total send request number: ", sendReqNum)

        timeEnd = time.time()
        timeUse = timeEnd - timeStart
        print("time use: ", timeUse)

    def checkMerchant(self):

        unavailableMerchantList = []

        print "===== start to check merchant id ====="

        for line in self.c:
            merchantID = line[2]

            m = Merchant.objects.filter(id=merchantID).first()
            if not m:
                unavailableMerchantList.append(line)
            else:
                self.availableMerchantIDList.append(line)

        print "=== result of check merchant id ==="
        print "num of unavailable line with merchant:"
        print len(unavailableMerchantList)
        print "content of unavailable line with merchant:"
        print unavailableMerchantList
        print "===== end to check merchant id ====="

    def checkCoupon(self):

        unavailableMerchantInfoSet = set()

        print "===== start to check coupon id ====="

        for line in self.availableMerchantIDList:

            doctorIDList = []
            couponList = []

            merchantID = line[2]
            couponID1 = line[3]
            couponID2 = line[4]
            couponList.append(couponID1)
            couponList.append(couponID2)

            # get merchant obj
            m = Merchant.objects.filter(id=merchantID).first()

            # get admin doctor
            adminDoctorID = m.doctor.id
            print "admin doctor", adminDoctorID

            # add admin doctor id to doctorIDList
            doctorIDList.append(adminDoctorID)

            # get other doctors
            doctors = MerchantRelevance.objects.filter(merchant_id=merchantID, doctor__doctor_type=DOCTOR_TYPE.DOCTOR)
            doctorCount = doctors.count()
            ds = doctors[0: doctorCount]
            otherDoctorList = [d.doctor.id for d in ds]

            doctorIDList.extend(otherDoctorList)
            print "doctor list: ", doctorIDList

            # get doctor of every coupon, find it is exist in doctor list
            for couponID in couponList:
                if couponID == 0:
                    continue

                c = Coupon.objects.filter(id=couponID).first()
                if not c:
                    unavailableMerchantInfoSet.add(merchantID)
                    continue

                createDoctor = c.doctor
                if not createDoctor:
                    unavailableMerchantInfoSet.add(merchantID)
                    continue

                createDoctorID = createDoctor.id

                # coupon's create doctor is not belong to merchant,
                # add to unavailableMerchantInfoSet
                if createDoctorID not in doctorIDList:
                    unavailableMerchantInfoSet.add(merchantID)
                    continue

                couponType = c.coupon_type

                # coupon's type is not COUPON_TYPES.DOCTOR,
                # add to unavailableMerchantInfoSet
                if couponType != COUPON_TYPES.DOCTOR:
                    unavailableMerchantInfoSet.add(merchantID)
                    continue

                distributionStatus = c.distribution_status

                # coupon's distribution status is not COUPON_DISTRIBUTION_STATUS.OPEN,
                # add to unavailableMerchantInfoSet
                if distributionStatus != COUPON_DISTRIBUTION_STATUS.OPEN:
                    unavailableMerchantInfoSet.add(merchantID)
                    continue

                timeType = c.time_type

                # if time type is COUPON_TIME_TYPE.START_END,
                # check start_time <= now <= end_time,
                # if incompatible, add to unavailableMerchantInfoSet
                if timeType == COUPON_TIME_TYPE.START_END:
                    startDataTime = c.start_time
                    endDataTime = c.end_time

                    nowTime = datetime.datetime.now()

                    if nowTime < startDataTime or nowTime > endDataTime:
                        unavailableMerchantInfoSet.add(merchantID)
                        continue

                # if can't find GiftToCoupon obj where coupon.id=couponID,
                # add to unavailableMerchantInfoSet
                couponGift = GiftToCoupon.objects.filter(coupon_id=couponID).first()
                if not couponGift:
                    unavailableMerchantInfoSet.add(merchantID)
                    continue

                # if coupon is not enable, add to unavailableMerchantInfoSet
                isEnable = couponGift.coupon_enable
                if not isEnable:
                    unavailableMerchantInfoSet.add(merchantID)
                    continue

        print "===== result of check coupon id ====="
        print "num of unavailable line with merchant and coupon:"
        print len(unavailableMerchantInfoSet)
        print "content of unavailable line with merchant and coupon:"
        print unavailableMerchantInfoSet
        print "===== end to check coupon id ====="

        for line in self.c:

            mid = line[2]

            if mid in unavailableMerchantInfoSet:
                continue

            self.availableMerchantIDListWithCoupon.append(line)

        print "===== available line with merchant and coupon ====="
        print self.availableMerchantIDListWithCoupon
        print "================ END ======================"

    @staticmethod
    def getGiftID(couponList):

        giftList = []

        for couponID in couponList:
            if couponID == 0:
                continue

            couponGift = GiftToCoupon.objects.filter(coupon_id=couponID).first()
            giftID = couponGift.coupon_gift.id
            giftList.append(giftID)

        return giftList
