# coding=utf-8
from __future__ import absolute_import, unicode_literals

import json

from django.conf import settings

from rpc.decorators import bind
from rpc.decorators import bind_context
from rpc.tool.error_code import CODES, gen

from api.models import CashBackOrder
from api.models import RefundOrder
from api.models import Person
from api.models import NEW_CASH_BACK_STATUS
from api.models import REFUND_STATUS
from api.models import ORDER_OPERATION_TYPE
from api.models import ORDER_OPERATION_ROLE
from api.models import Settlement, SETTLEMENT_STATUS
from api.manager import order_manager

from pay.models import Wechat, PaymentOrder
from pay.tool import wechat_pay_tool
from pay.tool.new_order_tool import refund_send_notification_and_sms
from pay.tool.new_order_tool import change_wechat_refund
from pay.tool.new_order_tool import cashback_send_notification_and_sms
from pay.tool.order_lock_tool import lock
from pay.tool.order_lock_tool import is_locked
from pay.tool.types import REFUND_TYPE
from pay.tool.new_order_tool import get_actual_refund_amount
from pay.tool.refund_tool import RefundTool
from gm_types.pay.union import REFUND_CODE
from gm_types.poseidon import AllPromotionType


@bind_context('pay/wechat/prepay', login_required=True)
def pay_wechat_prepay(ctx, settlement_id, ip, openid, is_mweb=True, is_wechat_app=False):
    # 默认这个接口都是M站PC站调用, 目前客户端微信支付在backend上
    try:
         settlement = Settlement.objects.get(pk=settlement_id)
    except Settlement.DoesNotExist:
        return gen(CODES.ORDER_NOT_FOUND)

    if settlement.status == SETTLEMENT_STATUS.PAID:
        return gen(CODES.SETTLEMENT_PAID)

    if settlement.status == SETTLEMENT_STATUS.CANCEL:
        return gen(CODES.SETTLEMENT_CANCELED)

    # is_wechat_app = False  # 统一走新app账号支付

    if is_wechat_app:
        wechat = wechat_pay_tool.get_wechat_obj_new_wechat_app()
        result = wechat.unifiedorder(
            settlement_id=settlement_id,
            ip=ip,
            fee=100 * settlement.real_payment,
            body=u'更美',
            detail=settlement.name,
            openid=openid,
            notify_url=settings.M_WECHAT_NOTIFY_URL
        )
    elif is_mweb:
        wechat = wechat_pay_tool.get_wechat_obj_new_mweb()
        result = wechat.unifiedorder(
            settlement_id=settlement_id,
            ip=ip,
            fee=100 * settlement.real_payment,
            body=u'更美',
            detail=settlement.name,
            openid=openid,
            notify_url=settings.M_WECHAT_NOTIFY_URL
        )
    else:
        wechat = wechat_pay_tool.get_wechat_obj_new_client_app()
        result = wechat.unifiedorder_for_app(
            out_trade_no=settlement_id,
            ip=ip,
            fee=100 * settlement.real_payment,
            body=u'更美',
            detail=settlement.name,
            notify_url=settings.M_WECHAT_NOTIFY_URL
        )

    return result


@bind("pay/wechat/refund/new")
def pay_wechat_refund(order_id):
    try:
        refund_order = RefundOrder.objects.get(order_id=order_id)
    except RefundOrder.DoesNotExist:
        RefundTool.add_refund_success_order(order_id)
        return gen(CODES.SUCCESS, message='订单{0}不存在'.format(order_id))


    # 退款时现算退款金额, 我是非常不赞成的
    # 最重要改成申请退款时, 就算出退款金额
    refund_order.fee = get_actual_refund_amount(refund_order.order)
    refund_order.save()

    try:
        payment_order = PaymentOrder.objects.get(orders=order_id)
    except PaymentOrder.DoesNotExist:
        RefundTool.add_refund_success_order(order_id)
        return gen(CODES.ORDER_CAN_NOT_REFUND)

    wechat_notify_data = json.loads(payment_order.notify_data)
    mch_id = wechat_notify_data['mch_id']
    wechat_app_id = wechat_notify_data['appid']
    if mch_id in settings.NEW_WECHAT_PID_LIST:
        wechat = wechat_pay_tool.get_wechat_obj_new_by_appid(wechat_app_id)
    else:
        wechat_obj_name = wechat_pay_tool.get_wechat_obj_name_by_appid(wechat_app_id)
        wechat = wechat_pay_tool.get_wechat_obj_by_name(wechat_obj_name)

    # 商户同意退款
    # 商户超时操作, 自动默认退款
    # 仲裁同意退款
    if refund_order.status not in (
            REFUND_STATUS.DOCTOR_APPROVE,
            REFUND_STATUS.REFUND_APPLY_SELLER_TIMEOUT,
            REFUND_STATUS.ARBIT_APPROVE):
        RefundTool.add_refund_success_order(order_id)
        return gen(CODES.SUCCESS,message='订单{0}退款状态{1}不能退款'.format(order_id,REFUND_STATUS.getDesc(refund_order.status)))

    operator = Person.objects.get(user_id=settings.BOSS)
    code,wechat_data = wechat.refund(payment_order.transaction_id, refund_order.id, payment_order.total_fee,
                                refund_order.fee * 100)
    if code == REFUND_CODE.SUCCESS:
        # TODO: 移到一起
        refund_order.order.operate(operator, ORDER_OPERATION_TYPE.REFUNDED, ORDER_OPERATION_ROLE.SYSTEM)

        from api.tool.order_tool import send_momo_stat_log_info_when_order_refunded
        send_momo_stat_log_info_when_order_refunded(refund_order.order)

        order_manager.send_order_refunded_event(refund_order.order)

        # TODO END
        refund_send_notification_and_sms(refund_order.order)
        change_wechat_refund(refund_order.order, wechat_data)
        RefundTool.add_refund_success_order(order_id)
        return gen(CODES.SUCCESS)
    else:
        optype = ORDER_OPERATION_TYPE.REFUND_ERROR
        if code == REFUND_CODE.CLOSED:
            optype = ORDER_OPERATION_TYPE.TAG_STALE_REFUND
            RefundTool.add_refund_success_order(order_id)

        refund_order.order.operate(operator, optype, ORDER_OPERATION_ROLE.SYSTEM)
        change_wechat_refund(refund_order.order, wechat_data)

        return gen(CODES.SUCCESS, message=REFUND_CODE.getDesc(code))


@bind("pay/wechat/cashback/new")
def pay_wechat_refund(order_id):
    try:
        cashback_order = CashBackOrder.objects.get(order_id=order_id)
    except CashBackOrder.DoesNotExist:
        return gen(CODES.SUCCESS, message='订单{0}不存在'.format(order_id))

    try:
        payment_order = PaymentOrder.objects.get(orders=order_id)
    except PaymentOrder.DoesNotExist:
        RefundTool.add_refund_success_order(order_id)
        return gen(CODES.SUCCESS, message='订单{0}不存在'.format(order_id))

    wechat_notify_data = json.loads(payment_order.notify_data)
    mch_id = wechat_notify_data['mch_id']
    wechat_app_id = wechat_notify_data['appid']
    if mch_id in settings.NEW_WECHAT_PID_LIST:
        wechat = wechat_pay_tool.get_wechat_obj_new_by_appid(wechat_app_id)
    else:
        wechat_obj_name = wechat_pay_tool.get_wechat_obj_name_by_appid(wechat_app_id)
        wechat = wechat_pay_tool.get_wechat_obj_by_name(wechat_obj_name)

    if cashback_order.status == NEW_CASH_BACK_STATUS.SUCCESS:
        RefundTool.add_refund_success_order(order_id)

    if cashback_order.status != NEW_CASH_BACK_STATUS.WAIT:
        RefundTool.add_refund_success_order(order_id)
        return gen(CODES.SUCCESS, message='订单{0}返现状态{1}不能返现'.format(order_id, NEW_CASH_BACK_STATUS.getDesc(cashback_order.status)))

    code, wechat_data = wechat.refund(payment_order.transaction_id, cashback_order.id, payment_order.total_fee,
                                cashback_order.fee * 100)

    operator = Person.objects.get(user_id=settings.BOSS)

    if code == REFUND_CODE.SUCCESS:
        lock(order_id, refund_type=REFUND_TYPE.CASHBACK)
        cashback_order.order.operate(operator, ORDER_OPERATION_TYPE.CASHBACKED, ORDER_OPERATION_ROLE.SYSTEM)
        cashback_send_notification_and_sms(cashback_order.order)
        change_wechat_refund(cashback_order.order, wechat_data)
        RefundTool.add_refund_success_order(order_id)
        return gen(CODES.SUCCESS)
    else:
        optype = ORDER_OPERATION_TYPE.CASHBACK_ERROR
        if code == REFUND_CODE.CLOSED:
            optype = ORDER_OPERATION_TYPE.TAG_STALE_CASHBACK
            RefundTool.add_refund_success_order(order_id)

        cashback_order.order.operate(operator, optype, ORDER_OPERATION_ROLE.SYSTEM)
        change_wechat_refund(cashback_order.order, wechat_data)
        return gen(CODES.SUCCESS, message=REFUND_CODE.getDesc(code))

def retry_do_refund(order_id):
    from rpc.context import create_fake_context
    ctx = create_fake_context()
    ctx.gaia_local['pay/wechat/refund/new'](order_id=order_id).unwrap()

def retry_do_cashback(order_id):
    from rpc.context import create_fake_context
    ctx = create_fake_context()
    ctx.gaia_local['pay/wechat/cashback/new'](order_id=order_id).unwrap()