# coding=utf-8
import datetime

from gm_types.gaia import GROUPBUY_STATUS

from api.models import ORDER_STATUS
from api.models import ORDER_OPERATION_TYPE
from api.models import CASH_BACK_STATUS
from api.models import REFUND_STATUS
from api.models import NEW_CASH_BACK_STATUS

from rpc.tool.error_code import CODES, gen

ORDER_ID_LEN = 10


def order_pay(order):
    if order.status in (ORDER_STATUS.NOT_PAID, ORDER_STATUS.PAYING, ORDER_STATUS.CANCEL):
        order.status = ORDER_STATUS.PAID
        return
    raise gen(CODES.ORDER_PAY_STATUS_ERROR)


def order_validate(order):
    if order.status != ORDER_STATUS.PAID:
        raise gen(CODES.ORDER_PAY_STATUS_ERROR)
    order.status = ORDER_STATUS.USED


def order_cancel(order):
    if order.status not in (ORDER_STATUS.NOT_PAID, ORDER_STATUS.PAYING):
        raise gen(CODES.ORDER_CAN_NOT_CANCEL)

    # 未付款订单可直接取消
    order.status = ORDER_STATUS.CANCEL


def order_apply_refund(order):
    from api.models import RefundOrder
    if order.payment == 0:
        raise gen(CODES.ORDER_REFUDN_PAYMENT_ERROR)
    order.status = ORDER_STATUS.WAIT_REFUNDED
    refund_order = RefundOrder.create_or_update(order=order, user_reason=order.refund_comment)
    if not refund_order:
        raise gen(CODES.ORDER_REFUDN_STATUS_ERROR)


def order_cancel_refund(order):
    payment = order.payment or order.real_payment
    if payment == 0 or order.status != ORDER_STATUS.WAIT_REFUNDED:
        raise gen(CODES.ORDER_REFUDN_CANCLE_STATUS_ERROR)
    order.status = ORDER_STATUS.PAID
    order.refund.status = REFUND_STATUS.CANCLED
    order.refund.save()


# def order_refund(order):
#     order.status = ORDER_STATUS.REFUNDED
#     order.refund.status = REFUND_STATUS.REFUNDED


def order_not_paid(order):
    order.status = ORDER_STATUS.NOT_PAID


def order_paying(order):
    order.status = ORDER_STATUS.PAYING


def order_cashback(order):
    order.cashback.status = CASH_BACK_STATUS.SUCCESS
    order.cash_back_status = CASH_BACK_STATUS.SUCCESS


def order_doctor_approve(order):
    refund = order.refund
    if refund.status != REFUND_STATUS.PROCESSING and order.status != ORDER_STATUS.USED:
        raise gen(CODES.ORDER_REFUDN_STATUS_ERROR)
    refund.status = REFUND_STATUS.DOCTOR_APPROVE
    refund.save(update_fields=["status"])


def order_groupbuy_fail(order):
    refund = order.refund
    if refund.status != REFUND_STATUS.PROCESSING:
        raise gen(CODES.ORDER_REFUDN_STATUS_ERROR)

    if order.groupbuy_status != GROUPBUY_STATUS.GROUPBUY_FAIL:
        raise gen(CODES.ORDER_REFUDN_STATUS_ERROR)

    refund.status = REFUND_STATUS.DOCTOR_APPROVE
    refund.save(update_fields=["status"])


def order_doctor_reject(order):
    refund = order.refund
    if refund.status != REFUND_STATUS.PROCESSING:
        raise gen(CODES.ORDER_REFUDN_STATUS_ERROR)
    refund.status = REFUND_STATUS.DOCTOR_REJECT
    refund.save()
    order.status = ORDER_STATUS.USED


# def order_appeal_arbit(order):
#     # 订单已使用不能申诉
#     # 医生没拒绝不能申诉
#     refund = order.refund
#     if refund.status != REFUND_STATUS.DOCTOR_REJECT and order.status != ORDER_STATUS.USED:
#         raise gen(CODES.ORDER_REFUDN_STATUS_ERROR)
#     refund.status = REFUND_STATUS.ARBITING
#     refund.save()
#     order.status = ORDER_STATUS.WAIT_REFUNDED


# def order_arbit_approve(order):
#     refund = order.refund
#     if refund.status != REFUND_STATUS.ARBITING and order.status != ORDER_STATUS.USED:
#         raise gen(CODES.ORDER_REFUDN_STATUS_ERROR)
#     refund.status = REFUND_STATUS.ARBIT_APPROVE
#     refund.save()
#     order.status = ORDER_STATUS.WAIT_REFUNDED


# def order_arbit_reject(order):
#     refund = order.refund
#     if refund.status != REFUND_STATUS.ARBITING:
#         raise gen(CODES.ORDER_REFUDN_STATUS_ERROR)
#     refund.status = REFUND_STATUS.ARBIT_REJECT
#     refund.save()
#     order.status = ORDER_STATUS.PAID


def order_refund_timeout(order):
    # 商家确认超时
    # 自动变为申请仲裁状态, 由运营同事退款
    refund = order.refund
    if refund.status != REFUND_STATUS.PROCESSING and order.status != ORDER_STATUS.USED:
        raise gen(CODES.ORDER_REFUDN_STATUS_ERROR)
    refund.status = REFUND_STATUS.REFUND_APPLY_SELLER_TIMEOUT
    refund.save()


def stale_refund(order):
    refund_order = order.refund
    if ORDER_STATUS.REFUNDED == order.status or REFUND_STATUS.REFUNDED == refund_order.status:
        raise gen(CODES.ORDER_REFUDN_HAS_BEEN_OPERATED)

    if not refund_order.stale:
        raise gen(CODES.ORDER_REFUDN_NOT_STALE)

    order.status = ORDER_STATUS.REFUNDED
    order.refund_time = datetime.datetime.now()

    refund_order.status = REFUND_STATUS.REFUNDED
    refund_order.refunded_at = datetime.datetime.now()
    refund_order.save()


def stale_cashback(order):
    cashback_order = order.cashback
    if CASH_BACK_STATUS.SUCCESS == order.cash_back_status or NEW_CASH_BACK_STATUS.SUCCESS == cashback_order.status:
        raise gen(CODES.ORDER_CASHBACK_HAS_BEEN_OPERATED)

    if not cashback_order.stale:
        raise gen(CODES.ORDER_CASHBACK_NOT_STALE)

    order.cash_back_status = CASH_BACK_STATUS.SUCCESS
    order.cash_back_time = datetime.datetime.now()

    cashback_order.status = NEW_CASH_BACK_STATUS.SUCCESS
    cashback_order.cashbacked_at = datetime.datetime.now()
    cashback_order.save()


def tag_stale_refund(order):
    refund_order = order.refund
    refund_order.stale = True
    refund_order.save()


def tag_stale_cashback(order):
    cashback_order = order.cashback
    cashback_order.stale = True
    cashback_order.save()


def order_has_refunded(order):
    now = datetime.datetime.now()
    refund_order = order.refund
    refund_order.status = REFUND_STATUS.REFUNDED
    refund_order.refunded_at = now
    refund_order.save()

    order.status = ORDER_STATUS.REFUNDED
    order.refund_time = now


def order_has_cashback(order):
    now = datetime.datetime.now()
    cashback_order = order.cashback
    cashback_order.status = NEW_CASH_BACK_STATUS.SUCCESS
    cashback_order.cashbacked_at = now
    cashback_order.save()

    order.cash_back_time = now
    order.cash_back_status = CASH_BACK_STATUS.SUCCESS


def refund_error(order):
    refund_order = order.refund
    refund_order.error = True
    refund_order.save()


def cashback_error(order):
    cashback_order = order.cashback
    cashback_order.error = True
    cashback_order.save()


# 已经在上一层增加了, transaction.atomic() 不要在函数里再加了
order_operate_map = {
    ORDER_OPERATION_TYPE.PAY: order_pay,
    ORDER_OPERATION_TYPE.VALIDATE: order_validate,
    ORDER_OPERATION_TYPE.CANCEL: order_cancel,
    ORDER_OPERATION_TYPE.APPLY_REFUND: order_apply_refund,
    ORDER_OPERATION_TYPE.CANCEL_REFUND: order_cancel_refund,
    ORDER_OPERATION_TYPE.STALE_REFUND: stale_refund,
    ORDER_OPERATION_TYPE.STALE_CASHBACK: stale_cashback,
    # ORDER_OPERATION_TYPE.APPEAL_ARBIT: order_appeal_arbit,
    ORDER_OPERATION_TYPE.NOT_PAID: order_not_paid,
    ORDER_OPERATION_TYPE.PAYING: order_paying,
    ORDER_OPERATION_TYPE.DOCTOR_APPROVE: order_doctor_approve,
    ORDER_OPERATION_TYPE.DOCTOR_REJECT: order_doctor_reject,
    # ORDER_OPERATION_TYPE.ARBIT_APPROVE: order_arbit_approve,
    # ORDER_OPERATION_TYPE.ARBIT_REJECT: order_arbit_reject,
    ORDER_OPERATION_TYPE.REFUND_TIMEOUT: order_refund_timeout,
    ORDER_OPERATION_TYPE.TAG_STALE_REFUND: tag_stale_refund,
    ORDER_OPERATION_TYPE.TAG_STALE_CASHBACK: tag_stale_cashback,
    ORDER_OPERATION_TYPE.REFUNDED: order_has_refunded,
    ORDER_OPERATION_TYPE.CASHBACKED: order_has_cashback,
    ORDER_OPERATION_TYPE.REFUND_ERROR: refund_error,
    ORDER_OPERATION_TYPE.CASHBACK_ERROR: cashback_error,

    ORDER_OPERATION_TYPE.GROUPBUY_FAIL: order_groupbuy_fail,

}
