#!coding=utf-8

from __future__ import unicode_literals, absolute_import, print_function
import json

from django.db import transaction

from api.tasks import order_task
from rpc.decorators import bind, bind_context
from rpc.tool.error_code import CODES, gen
from gm_types.pay import SUFPAY_STATUS
from gm_types.gaia import ORDER_STATUS
from gm_types.gaia import ORDER_OPERATION_TYPE
from gm_types.gaia import ORDER_OPERATION_ROLE
from api.tool.user_tool import get_user_from_context

from api.models import Doctor, Person
from api.models import Order
from weikuan.models import HospitalPay
from weikuan.manager.hospital_pay_manager import get_or_create_hospital_pay
from weikuan.views.pay import _refund_hospital_pay
from datetime import datetime
from pay.tool.alipay_tool import AlipayTool
from django.conf import settings
import threading
from pay.models import AlipayRefund
from pay.tool.refund_tool import RefundTool
from gm_types.pay.union import REFUND_CODE
@bind_context('api/hospital_pay/detail', login_required=True)
def hospital_pay_detail(ctx, hospital_pay_id):
    hospital_pay = HospitalPay.objects.get(id=hospital_pay_id)
    return hospital_pay.order_data()


@bind_context('api/hospital_pay/create', login_required=True)
def hospital_pay_create(ctx, order_id, device_id=None, ip=None):
    """创建尾款支付单"""
    try:
        order = Order.objects.get(pk=order_id, status=ORDER_STATUS.PAID)
    except:
        return gen(CODES.ORDER_NOT_FOUND)
    hospital_pay_id = get_or_create_hospital_pay(order)

    # 记录用户的设备标识,ip
    order_task.record_user_information.delay([order], hospital_pay_id, device_id, ip, ORDER_STATUS.NOT_PAID)
    result = {
        'hospital_pay_id': hospital_pay_id
    }
    return result


@bind_context('api/hospital_pay/cancel', login_required=True)
def hospital_pay_cancel(ctx, order_id, device_id, ip):
    with transaction.atomic():
        user = get_user_from_context(ctx)
        person = Person.objects.get(user=user)

        order = Order.objects.get(pk=order_id)
        if order.status not in [ORDER_STATUS.PAID]:
            raise Exception('订单状态[{0}]不支持退款'.format(ORDER_STATUS.getDesc(order.status)))

        hospital_pay = HospitalPay.objects.select_for_update().get(order_id=order_id)
        if user != hospital_pay.order.user:
            raise HospitalPay.DoesNotExist()

        if hospital_pay.status != SUFPAY_STATUS.PAID:
            raise Exception('尾款订单状态[{0}]不支持退款'.format(SUFPAY_STATUS.getDesc(hospital_pay.status)))

        RefundTool.add_weikuan_refund_applay_order(hospital_pay.id)

        hospital_pay.operate(person, ORDER_OPERATION_TYPE.APPLY_REFUND, ORDER_OPERATION_ROLE.USER)

        # 记录用户的设备标识,ip
        order_task.record_user_information.delay([order], hospital_pay.id, device_id, ip, ORDER_STATUS.WAIT_REFUNDED)

        threading.Timer(1, do_weikuan_refund, [user,hospital_pay]).start()

        return gen(CODES.SUCCESS)


def do_weikuan_refund(user,hospital_pay):
    refund_amount = hospital_pay.total_fee/100
    code,r = AlipayTool.refund(pid=settings.ALIPAY_USING_PARTNER,
                          trade_no=hospital_pay.transaction_id,
                          refund_amount=refund_amount,
                          refund_reason='协商退款',
                          out_request_no=str(hospital_pay.id),
                          operator_id='system')
    if code == REFUND_CODE.SUCCESS:
        RefundTool.add_weikuan_refund_success_order(hospital_pay.id)
        hospital_pay.operate(user.person, ORDER_OPERATION_TYPE.REFUNDED, ORDER_OPERATION_ROLE.USER)
        if r.get('fund_change') == 'Y':
            AlipayRefund.objects.create(order_no=hospital_pay.order_id,
                                        refund_fee=refund_amount,
                                        trade_no=r.get('trade_no'),
                                        batch_no=str(hospital_pay.id),
                                        trade_status="success",
                                        notify_id=REFUND_CODE.SUCCESS)
    else:
        if code == REFUND_CODE.PENDING:
            threading.Timer(60, do_weikuan_refund, [user, hospital_pay]).start()
        if code == REFUND_CODE.CLOSED:
            RefundTool.add_weikuan_refund_success_order(hospital_pay.id)
            hospital_pay.operate(user.person, ORDER_OPERATION_TYPE.TAG_STALE_REFUND, ORDER_OPERATION_ROLE.USER)
        else:
            hospital_pay.operate(user.person, ORDER_OPERATION_TYPE.REFUND_ERROR, ORDER_OPERATION_ROLE.USER)

        AlipayRefund.objects.create(order_no=hospital_pay.order_id,
                                    refund_fee=refund_amount,
                                    trade_no='none',
                                    batch_no=str(hospital_pay.id),
                                    trade_status=r.get('sub_msg'),
                                    notify_id=REFUND_CODE.FAIL)


@bind_context('api/hospital_pay/pay_jump', login_required=True)
def hospital_pay_jump(ctx, hospital_pay_id):
    with transaction.atomic():
        user = get_user_from_context(ctx)
        person = Person.objects.get(user=user)
        try:
            hospital_pay = HospitalPay.objects.select_for_update().get(id=hospital_pay_id)
            if hospital_pay.order.user != user:
                return HospitalPay.DoesNotExist()
        except HospitalPay.DoesNotExist:
            return gen(CODES.ORDER_NOT_FOUND)
        if hospital_pay.status in (SUFPAY_STATUS.PAYING):
            hospital_pay.operate(person, ORDER_OPERATION_TYPE.PAYING, ORDER_OPERATION_ROLE.USER)
            return gen(CODES.SUCCESS)
        return gen(CODES.ORDER_PAID)

