#!/usr/bin/env python
# -*- coding:utf-8 -*-
#
#   Author  :   zoumingzhe
#   E-mail  :   zoumingzhe@igengmei.com
#   Date    :   18/6/15 17:00
#   Desc    :   尾款支付单
from datetime import datetime
from django.db import models, transaction

from rpc.tool.error_code import CODES, gen

from gm_types.pay import SUFPAY_CHANNEL, SUFPAY_STATUS, INSTALLMENT_PERIOD
from gm_types.gaia import ORDER_SOURCE, ORDER_OPERATION_TYPE, ORDER_OPERATION_ROLE
from api.models import Order
from api.models import Person


class HospitalPay(models.Model):
    class Meta:
        verbose_name = u'尾款支付单信息'
        db_table = u'weikuan_hospital_pay'
        app_label = u'weikuan'

    id = models.CharField(max_length=12, verbose_name=u'尾款单号', primary_key=True)
    order = models.OneToOneField(Order, verbose_name=u'关联订单', related_name='hospital_pay')
    status = models.CharField(u'尾款状态', max_length=2, choices=SUFPAY_STATUS)
    total_fee = models.IntegerField(u'支付总金额, 分')

    channel = models.CharField(u'支付渠道', max_length=2, choices=SUFPAY_CHANNEL, null=True)
    period = models.CharField(u'分期周期', max_length=2, null=True)
    out_trade_no = models.CharField(u'商户订单号', max_length=32, null=True)
    transaction_id = models.CharField(u'第三方支付平台交易id', unique=True, max_length=50, null=True)
    account_name = models.CharField(u'支付账号', max_length=100, null=True)
    pay_start_time = models.DateTimeField(u'付款开始时间', null=True)
    paid_time = models.DateTimeField(u'付款完成时间', null=True)
    refund_time = models.DateTimeField(u'退款时间', null=True)
    # 商户id 退款预留字段
    account_seller_id = models.CharField(u'商户id', max_length=100)
    notify_data = models.TextField(u'支付通知信息(json)', null=True)
    create_at = models.DateTimeField(u'记录创建时间', auto_now_add=True)

    def operate(self, operator, optype, role, source=ORDER_SOURCE.UNKNOW):
        func = status_operate_map.get(optype)
        if func:
            try:
                with transaction.atomic():
                    func(self)
                    self.save()
                    HospitalPayOperation.objects.create(
                        hospital_pay=self,
                        operator=operator,
                        optype=optype,
                        role=role,
                        source=source,
                        operate_at=datetime.now()
                    )
                    return True
            except Exception as e:
                raise e
        else:
            raise Exception("error")


    def order_data(self):
        #尾款单信息
        data = {
            "doctor_id": self.order.service.doctor_id,
            "doctor_name": self.order.service.doctor.name,
            "doctor_user_id": self.order.service.doctor.user_id,
            "order_id": self.order_id,
            "order_name": self.order.service.name,
            "total_price": self.total_fee * 1.0 / 100,
            "period": self.period,
            "channel": self.channel,
            "status": self.status,
            "service_name": self.order.service.name,
            "service_id": self.order.service_id,
        }
        return data


class HospitalPayOperation(models.Model):
    class Meta:
        verbose_name = u'尾款单支付信息'
        verbose_name_plural = u'买单支付信息'
        db_table = u'weikuan_hospital_pay_operation'
        app_label = u'weikuan'

    hospital_pay = models.ForeignKey(HospitalPay)
    operator = models.ForeignKey(Person)
    optype = models.IntegerField(verbose_name=u'目标类型', choices=ORDER_OPERATION_TYPE,
                                 default=ORDER_OPERATION_TYPE.CREATE)
    role = models.IntegerField(verbose_name=u'操作角色', choices=ORDER_OPERATION_ROLE, default=ORDER_OPERATION_ROLE.USER)
    source = models.CharField(
        max_length=1, choices=ORDER_SOURCE, default=ORDER_SOURCE.UNKNOW,
        blank=True, verbose_name=u'操作来自哪个平台[iOS, Android, Web]'
    )
    operate_at = models.DateTimeField(null=True, blank=True, verbose_name=u'操作时间')


def paying(obj):
    obj.status = SUFPAY_STATUS.PAYING


def paid(obj):
    if obj.status == SUFPAY_STATUS.PAYING:
        obj.status = SUFPAY_STATUS.PAID
        return
    raise gen(CODES.ORDER_PAY_STATUS_ERROR)

def refunding(obj):
    if obj.status == SUFPAY_STATUS.PAID:
        obj.status = SUFPAY_STATUS.REFUNDING
        return
    raise gen(CODES.ORDER_REFUDN_STATUS_ERROR)

def failure(obj):
    if obj.status == SUFPAY_STATUS.REFUNDING:
        obj.status = SUFPAY_STATUS.FAILURE
        return
    raise gen(CODES.ORDER_REFUDN_STATUS_ERROR)

def refunded(obj):
    if obj.status == SUFPAY_STATUS.REFUNDING:
        obj.status = SUFPAY_STATUS.REFUNDED
        return
    raise gen(CODES.ORDER_REFUDN_STATUS_ERROR)

# 已在上层添加 atomic()
status_operate_map = {
    ORDER_OPERATION_TYPE.PAYING: paying,
    ORDER_OPERATION_TYPE.PAY: paid,
    ORDER_OPERATION_TYPE.APPLY_REFUND: refunding,
    ORDER_OPERATION_TYPE.REFUND_ERROR: failure,
    ORDER_OPERATION_TYPE.REFUNDED: refunded
}
