# -*- coding:utf-8 -*-
#
#   Author  :   zhangxiaolin
#   E-mail  :   petelin1120@gmail.com
#   Date    :   17/6/30 16:04
#   Desc    :   补单相关
from __future__ import unicode_literals, absolute_import, print_function
import datetime

from django.db import transaction
from django.db.utils import IntegrityError
from gm_types.doctor import BUDAN_LURU_OPERATE, BUDAN_LURU_STATUS, BDTRANSFER_APPLY_STATUS

from api.models import BuDanLuRu, BDTransferApplyRecord, BDTransferMonthlyWithdrawalToBudan
from api.models import BuDanLuRuOperate
from hera.queries.budan import BuDanDQ
from hera.queries.singlerecord import BuDanLuRuDQ
from rpc.cache import req_data_cache
from rpc.decorators import bind_context, cache_page
from rpc.tool.dict_mixin import to_dict
from rpc.tool.error_code import gen
from rpc.tool.error_code import CODES
from gm_types.gaia import BUDAN_STATUS, BUDAN_OPERATOR, BUDAN_OPERATE, BUDAN_TYPE, SINGLE_TYPE, BDTRANSFER_OBJECT_STATE
from gm_types.error import ERROR as GAIA_ERROR
from api.tool.buryiny_point_tool import budan_record
from api.models import BuDan, BuDanRecord, User, Doctor, Service, Order, json, BDTransferSingleRecord, BDTransfer
from rpc.tool.log_tool import info_logger
from .bdtransfer import bdtransfer_single_record_handler
from api.models import BuDanRealtedOrder, BDTransferMonth, BDTransferMonthToBudan, BDTransferToBudan


@bind_context('hera/budan/create')
def budan_create(ctx, data):
    """
    {'happen_time': 1498837098, 'service': '4639179', 'order': '9698843177', 'user': '20890778',
    'doctor': 'zzohylmrzs', 'extra_consume': 1.0, 'comment': '有客户980'}
    """
    pandan_id = data.pop("pandan_id", "")
    if data["doctor"] is None or not data["dev_projects"]:
        return gen(CODES.PARAMS_INVALID)

    if pandan_id:
        if BDTransferSingleRecord.objects.get(id=pandan_id).budan_id:
            return gen(CODES.BUDAN_RECORD_EXIST)

    budan = BuDan.create_budan(
        doctor_id=data['doctor'],
        dev_projects=data['dev_projects'],
        service_id=data['service'],
        order_id=data['order'],
        user_id=data['user'],
        happen_time=datetime.datetime.fromtimestamp(data['happen_time']),
        create_user=ctx.session.user,
        platform=BUDAN_OPERATOR.HERA,
        comment=data['comment'],
        user_phone=data['user_phone'],
        budan_type=data['budan_type'],
        total_gengmei_price=data.get('total_gengmei_price', 0),
        additional_amount=data.get('additional_amount', 0)
    )
    budan_id = budan.id
    if pandan_id:
        bdtransfer_single_record_handler.func(ctx, record_id=pandan_id, budan_id=budan_id)
    try:
        # 补单埋点, 暂时不处理异常
        ctx.logger.app(**budan_record(
            user_id=budan.user_id, order_id=budan.order_id,
            service_id=budan.service_id, dev_projects=budan.dev_projects
        ))
    except Exception:
        pass

    return budan_id


@bind_context('hera/budan/cancel')
def budan_cancel(ctx, budan_id, message, types=0):
    if types == BUDAN_TYPE.TRANSFER_BUDAN:
        # 转诊补单的撤销逻辑
        applyrecord = BDTransferToBudan.objects.filter(
            budan_id=budan_id
        ).last()
        if applyrecord and applyrecord.bdtransferapplyrecord.status != BDTRANSFER_APPLY_STATUS.REJECT:
            # 如果改转诊补单当月有补交记录, 且补交记录不为已驳回，则不允许撤销,
            raise gen(CODES.UNIVERSAL)

        obj = BDTransferSingleRecord.objects.get(budan_id=budan_id)
        obj.status = SINGLE_TYPE.HAS_CANCEL
        obj.save()

        budan = BuDan.objects.get(id=budan_id)
        budan.revocation_time = datetime.datetime.now()
        budan.save()

        status = None
        bd = BDTransferSingleRecord.objects.filter(dbtransfer_id=obj.dbtransfer_id)
        "如果有其他派单记录，状态优先级：已成单 > 已面诊 > 已预约 > 已派单"
        if not bd.exclude(status__in=[SINGLE_TYPE.HAS_CANCEL, SINGLE_TYPE.HAS_TERMINATE]).exists():
            status = BDTRANSFER_OBJECT_STATE.HAS_PASSED_INFOMATION
        elif bd.filter(status=SINGLE_TYPE.HAS_ORDER_FORM).exists():
            status = BDTRANSFER_OBJECT_STATE.SINGLE_FINISHED
        elif bd.filter(status=SINGLE_TYPE.HAS_CONSULTATION).exists():
            status = BDTRANSFER_OBJECT_STATE.HAS_CONSULTATION
        elif bd.filter(status=SINGLE_TYPE.HAS_APPOINTMENT).exists():
            status = BDTRANSFER_OBJECT_STATE.HAS_MADE_APPOINTMENT
        elif bd.filter(status=SINGLE_TYPE.NO_ORDER_FORM).exists():
            status = BDTRANSFER_OBJECT_STATE.HAS_SENT_SINGLE

        BDTransfer.objects.filter(id=obj.dbtransfer_id).update(object_state=status)

        bd_transfer = BDTransferMonth.objects.filter(
            doctor_id=obj.budan.doctor_id,
            month_at__year=datetime.datetime.now().year,
            month_at__month=datetime.datetime.now().month,
        ).first()
        if bd_transfer:
            bd_transfer.total_amount -= obj.budan.extra_consume
            bd_transfer.should_pay -= obj.budan.payment
            bd_transfer.save()

            if bd_transfer.should_pay == bd_transfer.already_pay:
                bd_transfer.is_finished = True
                bd_transfer.save()

            BDTransferMonthToBudan.objects.filter(
                budan_id=budan_id, bdtransfermonth=bd_transfer
            ).delete()
            budan = BuDan.objects.get(id=budan_id)
            budan.revocation_time = datetime.datetime.now()
            budan.save()

    return BuDan.objects.get(id=budan_id).cancel(ctx.session.user, BUDAN_OPERATOR.HERA, message)

@bind_context('hera/budan/cancel_v2')
def budan_cancel_v2(ctx, budan_id, message, types=0):
    if types == BUDAN_TYPE.TRANSFER_BUDAN:
        # 转诊补单的跨月撤销逻辑

        obj = BDTransferSingleRecord.objects.get(budan_id=budan_id)
        obj.status = SINGLE_TYPE.HAS_CANCEL
        obj.save()

        budan = BuDan.objects.get(id=budan_id)
        budan.is_monthly_revocation = True
        budan.revocation_time = datetime.datetime.now()
        budan.save()

        status = None
        bd = BDTransferSingleRecord.objects.filter(dbtransfer_id=obj.dbtransfer_id)
        if not bd.exclude(status__in=[SINGLE_TYPE.HAS_CANCEL, SINGLE_TYPE.HAS_TERMINATE]).exists():
            status = BDTRANSFER_OBJECT_STATE.HAS_PASSED_INFOMATION
        elif bd.filter(status=SINGLE_TYPE.HAS_CONSULTATION).exists():
            status = BDTRANSFER_OBJECT_STATE.HAS_CONSULTATION
        elif bd.filter(status=SINGLE_TYPE.HAS_APPOINTMENT).exists():
            status = BDTRANSFER_OBJECT_STATE.HAS_MADE_APPOINTMENT
        elif bd.filter(status=SINGLE_TYPE.NO_ORDER_FORM).exists():
            status = BDTRANSFER_OBJECT_STATE.HAS_SENT_SINGLE

        BDTransfer.objects.filter(id=obj.dbtransfer_id).update(object_state=status)

        bdtransfermonth_id = BDTransferMonthToBudan.objects.get(budan_id=budan_id).bdtransfermonth_id
        bd_transfer_v1 = BDTransferMonth.objects.filter(
            id=bdtransfermonth_id
        ).first()
        if bd_transfer_v1:
            bd_transfer_v1.total_amount -= obj.budan.extra_consume
            bd_transfer_v1.should_pay -= obj.budan.payment
            bd_transfer_v1.save()

        bd_transfer = BDTransferMonth.objects.filter(
            doctor_id=obj.budan.doctor_id,
            month_at__year=obj.budan.create_time.year,
            month_at__month=obj.budan.create_time.month,
        ).first()
        if bd_transfer:
            bd_transfer.monthly_total_amount += obj.budan.extra_consume
            bd_transfer.monthly_should_pay += obj.budan.payment
            bd_transfer.save()

            if bd_transfer.should_pay == bd_transfer.already_pay:
                bd_transfer.is_finished = True
                bd_transfer.save()

            BDTransferMonthlyWithdrawalToBudan.objects.get_or_create(
                bdtransfermonth_id=bd_transfer.id, budan_id=budan_id
            )
            BDTransferMonthToBudan.objects.filter(
                budan_id=budan_id
            ).delete()

    return BuDan.objects.get(id=budan_id).cancel(ctx.session.user, BUDAN_OPERATOR.HERA, message)

@bind_context('hera/budan/reject')
def budan_cancel(ctx, budan_id, message):
    return BuDan.objects.get(id=budan_id).reject(ctx.session.user, message)


@bind_context('hera/budan/luru_get')
def budan_luru_get(ctx, budan_luru_id):
    """
    根据ID获取补单录入的ID
    :param ctx:
    :param budan_luru_id:
    :return:
    """
    if not budan_luru_id:
        raise gen(CODES.PARAMS_INVALID)

    budan_luru = BuDanLuRu.objects.get(id=budan_luru_id)
    return budan_luru.get_data()


@bind_context('hera/budan/luru_edit')
def budan_luru_edit(ctx, info):
    """
    新添加补单录入数据
    :param ctx:
    :param info:
    :return:
    """
    with transaction.atomic():
        luru = BuDanLuRu.objects.create(**info)
        BuDanLuRuOperate.objects.create(
            budanluru=luru,
            user=ctx.session.user.person,
            operate=BUDAN_LURU_OPERATE.ENTER
        )

    return luru.id


@bind_context('hera/budan/luru_undo')
def budan_luru_undo(ctx, luru_id):
    """
    撤销补单录入
    :param ctx:
    :param luru_id:
    :return:
    """
    luru = BuDanLuRu.objects.get(id=luru_id)
    if not luru.can_undo:
        raise gen(CODES.BUDAN_STATUS_ERROR)
    with transaction.atomic():
        luru.status = BUDAN_LURU_STATUS.REVOKED
        luru.save()
        BuDanLuRuOperate.objects.create(
            budanluru=luru,
            user=ctx.session.user.person,
            operate=BUDAN_LURU_OPERATE.UNDO
        )


@bind_context('hera/budan/luru/query')
def budan_luru_query(ctx, options):
    dtobj = BuDanLuRuDQ()
    return dtobj.process(**options)


@bind_context('hera/budan/exsits_related_order')
def exsits_related_order(ctx, order_id):
    """
    Judging the order whether has been related or not by order's id
    :param ctx:
    :param order_id:
    :return:
    """
    data = dict()
    is_exists_data = BuDanRealtedOrder.objects.filter(order_id=order_id, is_delete=False).first()
    if is_exists_data:
        data.update({
            'order_id': order_id,
            'budan_id': is_exists_data.budan_id,
            'created_time': is_exists_data.created_time.strftime('%Y-%m-%d %H:%M:%S')
        })
        return data
    return data


@bind_context('hera/budan/save_related_order')
def save_related_order(ctx, data, budan_id):
    """
    Save budan
    :param ctx:
    :param data:
    :return:
    """
    if not isinstance(data, list):
        return 0
    list_item = list()
    for item in data:
        list_item.append(BuDanRealtedOrder(
            order_id=item.get('order_id'),
            budan_id=budan_id,
            service_id=item.get('service_id'),
            service_name=item.get('service_name'),
            gengmei_price=item.get('gengmei_price'),
            commission_rate=item.get('commission_rate'),
            commission_amount=item.get('commission_amount'),
            additional_amount=item.get('additional_amount'),
            is_delete=False
        ))
    result = BuDanRealtedOrder.objects.bulk_create(list_item)
    return len(result)


@bind_context('hera/budan/related_orders')
def budan_related_orders(ctx, budan_id):
    """
    Get orders by budan's id
    :param ctx:
    :param budan_id:
    :return:
    """
    data = list()
    list_data = BuDanRealtedOrder.objects.filter(budan_id=budan_id)

    for item in list_data:
        data.append({
            'budan_id': budan_id,
            'order_id': item.order_id,
            'service_id': item.service_id,
            'service_name': item.service_name,
            'created_time': item.created_time.strftime('%Y-%m-%d %H:%M:%S'),
            'gengmei_price': item.gengmei_price,
            'commission_rate': item.commission_rate,
            'commission_amount': item.commission_amount,
            'additional_amount': item.additional_amount
        })
    return data

@bind_context('hera/budan/related_orders/delete')
def delete_related_orders(ctx, budan_id):
    ref_orders = BuDanRealtedOrder.objects.filter(budan_id=budan_id, is_delete=False).update(is_delete=True)
    return ref_orders

@bind_context('hera/budan/select/bdtransferapplyrecord')
def select_bdtransferapplyrecord(ctx, budan_id):
    try:
        bdtransferapplyrecord_id = BDTransferToBudan.objects.get(budan_id=budan_id).bdtransferapplyrecord.id
        status = BDTransferApplyRecord.objects.get(id=bdtransferapplyrecord_id).status
        if status not in [BDTRANSFER_APPLY_STATUS.PENDING, BDTRANSFER_APPLY_STATUS.SUCCESS]:
            return 0
        else:
            return 1
    except:
        return 0
