# coding=utf-8

from django.db import models
from django.db.models import Q
from django.conf import settings
from django.utils import timezone

from apps.customer.models import Customer
from apps.order.models import Order
from apps.customer.models import SuperiorDistributor

from utils.exceptions import CustomError

'''
现金返利及现金变动记录
'''


class CashLog(models.Model):
    CASH_REBATE = 1
    CASH_TRANSFER = 2
    TYPE_CHOICES = (
        (CASH_REBATE, u'现金返利'),
        (CASH_TRANSFER, u'返利提现'),
    )

    customer = models.ForeignKey(Customer, verbose_name=u'客户', on_delete=models.PROTECT)
    type = models.PositiveSmallIntegerField(choices=TYPE_CHOICES, verbose_name=u"类型")
    happen_time = models.DateTimeField(verbose_name=u"发生时间", default=timezone.now)
    amount = models.BigIntegerField(verbose_name=u"变动额")
    balance = models.BigIntegerField(verbose_name=u"余额")

    class Meta:
        db_table = "cash_log"
        verbose_name = u'现金日志'
        ordering = ['-happen_time',]
        index_together = (
            'happen_time',
        )
        default_permissions = ()
        permissions = []

    @staticmethod
    def addnew(customer, type, amount):
        customer.balance += amount
        # if customer.balance < 0:
        #     raise CustomError(u'用户余额不足！')
        customer.save()
        instance = CashLog.objects.create(
            customer=customer,
            type=type,
            happen_time=timezone.now(),
            amount=amount,
            balance=customer.balance
        )
        return instance


class CashRebate(models.Model):

    order = models.ForeignKey(Order, verbose_name=u'订单', related_name='cash_rebate_order', editable=False, on_delete=models.PROTECT)
    ratio = models.FloatField(verbose_name=u'返利比例', default=0)
    amount = models.BigIntegerField(verbose_name=u'返利金额', default=0)
    customer = models.ForeignKey(Customer, verbose_name=u'客户', editable=False, on_delete=models.PROTECT)
    create_time = models.DateTimeField(verbose_name=u"创建时间", default=timezone.now, editable=False)

    class Meta:
        db_table = "cash_rebate"
        verbose_name = u'现金返利'
        ordering = []
        index_together = ()
        default_permissions = ()
        permissions = []


class CashRebateLog(models.Model):
    rebate = models.OneToOneField(CashRebate, verbose_name=u'现金返利', related_name='rebate', editable=False, on_delete=models.PROTECT)
    log = models.OneToOneField(CashLog, verbose_name=u'日志', related_name='rebate_log', editable=False, on_delete=models.PROTECT)

    class Meta:
        db_table = "cash_rebate_log"
        verbose_name = u'现金返利日志'
        ordering = []
        index_together = ()
        default_permissions = ()
        permissions = []

    @staticmethod
    def addnew(rebate):
        customer = Customer.objects.select_for_update().filter(id=rebate.customer.id).first()
        log = CashLog.addnew(customer, CashLog.CASH_REBATE, rebate.amount)
        instance = CashRebateLog.objects.create(rebate=rebate, log=log)
        return instance


class TransferCashRebate(models.Model):
    DEFAULT = 0     # 未处理  没有申请转账
    ACCEPTED = 1    # 已受理。
    PROCESSING = 2  # 转账中。已开始处理批次内的转账明细单
    WAIT_PAY = 3    # 待付款  商户员工确认付款阶段
    FINISHED = 4    # 已完成。批次内的所有转账明细单都处理完成
    CLOSED = 5      # 已关闭。可查询具体的批次关闭原因
    STATUS = (
        (DEFAULT, u'未处理'),
        (ACCEPTED, u'已受理'),
        (PROCESSING, u'转账中'),
        (WAIT_PAY, u'待付款'),
        (FINISHED, u'已完成'),
        (CLOSED, u'已关闭'),
    )

    order = models.ForeignKey(Order, verbose_name=u'订单', related_name='transfer_order', editable=False, on_delete=models.PROTECT)
    no = models.CharField(max_length=50, verbose_name=u'批次号', editable=False, null=True, blank=True)
    transfer_status = models.PositiveSmallIntegerField(choices=STATUS, verbose_name=u"返利转账状态", default=DEFAULT)
    batch_id = models.CharField(verbose_name=u"微信批次单号", max_length=100, null=True, blank=True)
    transfer_time = models.DateTimeField(verbose_name=u"批次创建时间", null=True, blank=True)
    transfer_amount = models.BigIntegerField(verbose_name=u'转账总金额', default=0, editable=False)
    transfer_num = models.IntegerField(verbose_name=u'转账总笔数', default=0, editable=False)
    success_amount = models.BigIntegerField(verbose_name=u'转账成功金额', default=0, editable=False)
    success_num = models.IntegerField(verbose_name=u"转账成功笔数", default=0, editable=False)
    fail_amount = models.BigIntegerField(verbose_name=u"转账失败金额", default=0, editable=False)
    fail_num = models.IntegerField(verbose_name=u"转账失败笔数", default=0, editable=False)
    update_time = models.DateTimeField(verbose_name=u"批次更新时间", null=True, blank=True)
    close_reason = models.CharField(verbose_name=u"批次关闭原因", max_length=100, null=True, blank=True)

    class Meta:
        db_table = "transfer"
        verbose_name = u'返利转账'
        ordering = ['id']
        index_together = ()
        unique_together = (
            'no',
        )
        default_permissions = ()
        permissions = []


class TransferCashRebateDetail(models.Model):
    DEFAULT = 0
    PENDING = 1
    SUCCESS = 2
    FAIL = 3
    STATUS_CHOICES = (
        (DEFAULT, u'未处理'),
        (PENDING, u'转账中'),  # 正在处理中，转账结果尚未明确
        (SUCCESS, u'转账成功'),
        (FAIL, u'转账失败'),  # 需要确认失败原因后，在决定是否重新发起对该笔明细单的转账(并非真个转账批次单)  重新发起转账  需要新的批次号重新发起转账
    )

    no = models.CharField(max_length=50, verbose_name=u'单号', editable=False, null=True, blank=True)
    main = models.ForeignKey(TransferCashRebate, verbose_name=u'转账', related_name='transfer_detail_main', editable=False, on_delete=models.PROTECT)
    rebate = models.ForeignKey(CashRebate, verbose_name=u'返利', related_name='transfer_detail_Rebate', editable=False, on_delete=models.PROTECT)
    amount = models.BigIntegerField(verbose_name=u'返利金额', default=0)
    customer = models.ForeignKey(Customer, verbose_name=u'客户', editable=False, on_delete=models.PROTECT)
    create_time = models.DateTimeField(verbose_name=u"创建时间", default=timezone.now, editable=False)
    detail_no = models.CharField(verbose_name=u"微信明细单号", max_length=100, null=True, blank=True)
    status = models.PositiveSmallIntegerField(choices=STATUS_CHOICES, verbose_name=u"转账状态", default=DEFAULT)
    fail_reason = models.CharField(max_length=1000, verbose_name=u"转账失败原因", null=True, blank=True)
    initiate_time = models.DateTimeField(verbose_name=u'转账发起时间', null=True, blank=True)
    update_time = models.DateTimeField(verbose_name=u'明细更新时间', null=True, blank=True)

    class Meta:
        db_table = "transfer_detail"
        verbose_name = u'返利转账明细'
        ordering = ['id', ]
        index_together = ()
        unique_together = (
            'no',
        )
        default_permissions = ()
        permissions = []


class CashTransferLog(models.Model):
    transfer = models.OneToOneField(TransferCashRebateDetail, verbose_name=u'返利转账', related_name='transfer', editable=False, on_delete=models.PROTECT)
    log = models.OneToOneField(CashLog, verbose_name=u'日志', related_name='transfer_log', editable=False, on_delete=models.PROTECT)

    class Meta:
        db_table = "cash_transfer_log"
        verbose_name = u'现金返利提现日志'
        ordering = []
        index_together = ()
        default_permissions = ()
        permissions = []

    @staticmethod
    def addnew(transfer):
        customer = Customer.objects.select_for_update().filter(id=transfer.customer.id).first()
        log = CashLog.addnew(customer, CashLog.CASH_TRANSFER, -transfer.amount)
        instance = CashTransferLog.objects.create(transfer=transfer, log=log)
        return instance


'''
积分返利及积分变动记录
'''


class PointLog(models.Model):

    POINT_REBATE = 1
    POINT_ORDER = 2
    POINT_GIVE = 3
    POINT_CANCEL = 4
    TYPE_CHOICES = (
        (POINT_REBATE, u'积分返利'),
        (POINT_ORDER, u'积分兑换商品'),
        (POINT_GIVE, u'购买商品赠送积分'),  # 购买商品赠送的积分
        (POINT_CANCEL, u'取消订单返还积分'),  # 取消订单的时候将已扣除的积分返还
    )

    customer = models.ForeignKey(Customer, verbose_name=u'客户', on_delete=models.PROTECT)
    type = models.PositiveSmallIntegerField(choices=TYPE_CHOICES, verbose_name=u"类型")
    happen_time = models.DateTimeField(verbose_name=u"发生时间", default=timezone.now)
    amount = models.IntegerField(verbose_name=u"变动额")
    balance = models.IntegerField(verbose_name=u"余额")

    class Meta:
        db_table = "point_log"
        verbose_name = u'积分日志'
        ordering = ['-happen_time',]
        index_together = (
            'happen_time',
        )
        default_permissions = ()
        permissions = []

    @staticmethod
    def addnew(customer, type, point):
        customer.points += point
        if customer.points < 0:
            raise CustomError(u'用户积分不足！')
        customer.save()
        instance = PointLog.objects.create(
            customer=customer,
            type=type,
            happen_time=timezone.now(),
            amount=point,
            balance=customer.points
        )
        return instance


class PointRebate(models.Model):

    order = models.ForeignKey(Order, verbose_name=u'订单', related_name='point_rebate_order', editable=False, on_delete=models.PROTECT)
    ratio = models.FloatField(verbose_name=u'返利比例', default=0)
    amount = models.IntegerField(verbose_name=u'返利积分', default=0)
    customer = models.ForeignKey(Customer, verbose_name=u'客户', editable=False, on_delete=models.PROTECT)
    create_time = models.DateTimeField(verbose_name=u"创建时间", default=timezone.now, editable=False)

    class Meta:
        db_table = "point_rebate"
        verbose_name = u'积分返利'
        ordering = []
        index_together = ()
        default_permissions = ()
        permissions = []


class PointGive(models.Model):

    order = models.ForeignKey(Order, verbose_name=u'订单', related_name='point_give_order', editable=False, on_delete=models.PROTECT)
    ratio = models.FloatField(verbose_name=u'赠送比例', default=0)
    amount = models.IntegerField(verbose_name=u'赠送积分', default=0)
    customer = models.ForeignKey(Customer, verbose_name=u'客户', editable=False, on_delete=models.PROTECT)
    create_time = models.DateTimeField(verbose_name=u"创建时间", default=timezone.now, editable=False)

    class Meta:
        db_table = "point_give"
        verbose_name = u'积分返利'
        ordering = []
        index_together = ()
        default_permissions = ()
        permissions = []


class PointLogOrder(models.Model):

    order = models.ForeignKey(Order, verbose_name=u'订单', related_name='order', editable=False, on_delete=models.PROTECT)
    log = models.OneToOneField(PointLog, verbose_name=u'日志', related_name='order_log', editable=False, on_delete=models.PROTECT)

    class Meta:
        db_table = "point_log_order"
        verbose_name = u'积分兑换日志'
        ordering = []
        index_together = ()
        default_permissions = ()
        permissions = []

    @staticmethod
    def addnew(order, cancel_order=False):
        customer = Customer.objects.select_for_update().filter(id=order.customer.id).first()
        total_point = -order.total_point
        type = PointLog.POINT_ORDER
        if cancel_order:
            # 如果是作废订单就将订单积分加上去
            total_point = order.total_point
            type = PointLog.POINT_CANCEL
        log = PointLog.addnew(customer, type, total_point)
        instance = PointLogOrder.objects.create(order=order, log=log)
        return instance


class PointRebateLog(models.Model):
    rebate = models.OneToOneField(PointRebate, verbose_name=u'积分返利', related_name='rebate', editable=False, on_delete=models.PROTECT)
    log = models.OneToOneField(PointLog, verbose_name=u'日志', related_name='rebate_log', editable=False, on_delete=models.PROTECT)

    class Meta:
        db_table = "point_log_rebate"
        verbose_name = u'积分返利日志'
        ordering = []
        index_together = ()
        default_permissions = ()
        permissions = []

    @staticmethod
    def addnew(rebate):
        customer = Customer.objects.select_for_update().filter(id=rebate.customer.id).first()
        log = PointLog.addnew(customer, PointLog.POINT_REBATE, rebate.amount)
        instance = PointRebateLog.objects.create(rebate=rebate, log=log)
        return instance


class PointGiveLog(models.Model):
    give = models.OneToOneField(PointGive, verbose_name=u'赠送积分', related_name='give', editable=False, on_delete=models.PROTECT)
    log = models.OneToOneField(PointLog, verbose_name=u'日志', related_name='give_log', editable=False, on_delete=models.PROTECT)

    class Meta:
        db_table = "point_log_give"
        verbose_name = u'赠送积分日志'
        ordering = []
        index_together = ()
        default_permissions = ()
        permissions = []

    @staticmethod
    def addnew(give):
        customer = Customer.objects.select_for_update().filter(id=give.customer.id).first()
        log = PointLog.addnew(customer, PointLog.POINT_GIVE, give.amount)
        instance = PointGiveLog.objects.create(give=give, log=log)
        return instance
