# coding=utf-8

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

from apps.option.models import Option
from apps.config.models import Config
from apps.commodity.models import Commodity
from apps.customer.models import Customer, CustomerAddress, SuperiorDistributor
from utils.exceptions import CustomError
from utils.wechatpay import WechatPay, WeChatResponse


class Pay(models.Model):
    WAIT = 1
    PAY = 2
    UNDO = 3
    STATUS_CHOICES = (
        (WAIT, u'待付款'),
        (PAY, u'已付款'),
        (UNDO, u'已取消'),
    )

    no = models.CharField(max_length=64, verbose_name=u"单号")
    status = models.PositiveSmallIntegerField(choices=STATUS_CHOICES, verbose_name=u'状态', default=WAIT)
    precreate_amount = models.BigIntegerField(verbose_name=u"预支付金额")
    amount = models.BigIntegerField(verbose_name=u"支付金额", null=True)
    transaction_id = models.CharField(max_length=100, verbose_name=u"微信支付订单号", null=True)
    customer = models.ForeignKey(Customer, verbose_name=u'下单人', related_name='pay_customer', on_delete=models.PROTECT)
    create_time = models.DateTimeField(verbose_name=u"创建时间", default=timezone.now)

    class Meta:
        db_table = "pay"
        verbose_name = u"支付信息"
        ordering = ('-id',)
        index_together = (
            'create_time',
            'status',
        )
        unique_together = (
            'no',
        )
        default_permissions = ()

    @staticmethod
    def wechatPay(amount, customer, appid, openid):
        instance = Pay._addnew(amount, customer)
        return instance, instance._wechatUnifiedOrder(appid, openid)

    @staticmethod
    def _addnew(amount, customer):
        if amount <= 0:
            raise CustomError(u'无效的付款金额！')
        pay_no = '{}{}'.format(timezone.now().strftime('%y%m%d%H%M%S'), str(customer.id))
        pay = Pay.objects.create(no=pay_no, status=Pay.WAIT, precreate_amount=amount, customer=customer)
        return pay

    def _wechatUnifiedOrder(self, appid, openid):
        wechatpay = WechatPay(appid)
        wechatpay.unifiedOrder(self.no, self.precreate_amount, openid)
        data = wechatpay.getAppString()
        return data

    @staticmethod
    def getByNo(no):
        instance = Pay.objects.filter(no=no).first()
        if not instance:
            raise CustomError(u'未找到相应的支付单!')
        return instance

    def payClosed(self):
        if self.status != Pay.WAIT:
            return
        self.status = Pay.UNDO
        self.save()

    def payConfirm(self, amount, transaction_id):
        if self.status != Pay.WAIT:
            return

        self.status = Pay.PAY
        self.amount = amount
        self.transaction_id = transaction_id
        self.save()
        order = Order.objects.filter(pay=self).first()
        if order:
            order.orderPayConfirm()


class ShoppingCart(models.Model):
    commodity_details = models.ForeignKey(Commodity, verbose_name=u'产品明细', on_delete=models.PROTECT)
    quantity = models.PositiveIntegerField(verbose_name=u'数量', default=1)
    create_time = models.DateTimeField(verbose_name=u'创建时间', auto_now_add=True)
    customer = models.ForeignKey(Customer, related_name='shopping_cart_customer', verbose_name=u"下单人", on_delete=models.PROTECT, editable=False)

    class Meta:
        db_table = 'shopping_cart'
        verbose_name = u'购物车'
        ordering = ['-id', ]
        default_permissions = ()


class Order(models.Model):
    WAIT_PAY = 0
    WAIT_DISPATCH = 1
    CONFIRM_DISPATCH = 2
    CANCEL = 3
    STATUS_CHOICES = (
        (WAIT_PAY, u'待付款'),
        (WAIT_DISPATCH, u'待发货'),
        (CONFIRM_DISPATCH, u'已发货'),
        (CANCEL, u'已取消'),
    )

    no = models.CharField(max_length=50, verbose_name=u'订单号', editable=False, null=True, blank=True)
    pay = models.ForeignKey(Pay, verbose_name=u'支付信息', on_delete=models.PROTECT, null=True, editable=False)

    total_count = models.IntegerField(verbose_name=u'总数量', default=0, editable=False)
    total_amount = models.BigIntegerField(verbose_name=u'总金额', default=0, editable=False)
    total_point = models.IntegerField(verbose_name=u'总积分', default=0, editable=False)
    status = models.PositiveSmallIntegerField(choices=STATUS_CHOICES, verbose_name=u"订单状态", default=WAIT_PAY)
    notes = models.CharField(max_length=500, verbose_name=u"备注", null=True, blank=True)
    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)

    cancel_reason = models.CharField(max_length=100, verbose_name=u"取消原因", null=True, blank=True)
    cancel_user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='order_cancel_user', verbose_name=u"取消人", on_delete=models.PROTECT, null=True, blank=True)
    cancel_time = models.DateTimeField(verbose_name=u"取消时间", null=True, blank=True)

    address = models.ForeignKey(CustomerAddress, verbose_name=u'收货地址', related_name='order_address', null=True, blank=True, on_delete=models.PROTECT)
    name = models.CharField(verbose_name=u'收货人', max_length=20, null=True, blank=True)
    tel = models.CharField(verbose_name=u'收货电话', max_length=15, null=True, blank=True)
    user_address = models.CharField(verbose_name=u'详细地址', max_length=200, null=True, blank=True)

    express_no = models.CharField(max_length=50, verbose_name=u'快递单号', null=True, blank=True)
    express_company = models.ForeignKey(Option, verbose_name=u'快递公司', on_delete=models.PROTECT, null=True, blank=True)
    dispatch_time = models.DateTimeField(verbose_name=u'发货时间', null=True, blank=True)
    dispatch_user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='order_dispatch_user', verbose_name=u"发货人", on_delete=models.PROTECT, null=True, blank=True)

    class Meta:
        db_table = "order"
        verbose_name = u"客户订单"
        ordering = ('-id',)
        index_together = ('status', 'create_time', 'no', )
        default_permissions = ()
        permissions = []

    def generateNo(self):
        '''
        生成订单的订单号(注意：该函数最后没有 save 要在调用该函数后save )
        :return:
        '''
        no = '{}{}{:0>4}'.format('XCX', timezone.now().strftime('%Y%m%d'), self.id)
        self.no = no

    def set_order_adderss(self, address_id):
        '''
        下单时保存用户选择的收货地址(注意：该函数最后没有 save 要在调用该函数后save )
        :param address_id: 收货地址id
        :return:
        '''
        address = CustomerAddress.objects.filter(id=address_id).first()
        if not address:
            raise CustomError(u'请选择正确的收货地址！')
        if address.delete:
            raise CustomError(u'该收货地址已删除，请选择重新选择收货地址！')
        self.address = address
        self.name = address.name
        self.tel = address.tel
        self.user_address = address.get_address()

    def set_order_detail(self, details):
        '''
        下单时保存选择的商品明细(注意：该函数最后没有 save 要在调用该函数后save )
        :param details: 商品明细
        :return:
        '''
        total_count = total_amount = total_point = 0
        create_data = []
        for item in details:
            commodity = Commodity.objects.filter(id=item['id']).first()
            if not commodity:
                raise CustomError(u'您选择的商品不存在，请刷新后重新选择！')
            if commodity.delete:
                raise CustomError(u'商品【{}】已下架！'.format(commodity.name))
            if commodity.status != settings.ONLINE:
                raise CustomError(u'商品【{}】已下架！'.format(commodity.name))

            try:
                count = int(item['count'])
            except:
                raise CustomError(u'商品数量错误，请重新选择！')
            if count <= 0:
                raise CustomError(u'商品数量错误，请重新选择！')

            amount = point_amount = 0
            if commodity.type == Commodity.POINT:
                point_amount = commodity.point_price * count
            elif commodity.type == Commodity.CASH:
                amount = commodity.price * count
            else:
                continue

            d = OrderDetails(
                order=self,
                commodity=commodity,
                price=commodity.price,
                point=commodity.point_price,
                count=count,
                amount=amount,
                point_amount=point_amount
            )

            create_data.append(d)

            total_point += point_amount
            total_amount += amount
            total_count += count

        OrderDetails.objects.bulk_create(create_data)
        self.total_count = total_count
        self.total_amount = total_amount
        self.total_point = total_point

    def pointConfirm(self):
        '''
        积分兑换 确认兑换成功  当只购买了积分商品的时候 使用本函数确认  有现金商品的时候使用pay下边的确认函数确认
        注意 order最后没有save()  在调用该函数后order要save()
        :return:
        '''
        if self.status != Order.WAIT_PAY:
            return
        self.status = Order.WAIT_DISPATCH
        commodity_id = Config.get_commodity()
        # 这一点儿不能用这个  不然 数据customer数据重新保存了 积分那一块儿的就不行了
        customer = Customer.objects.filter(id=self.customer.id).first()

        detail = OrderDetails.objects.filter(order=self)
        for item in detail:
            commodity = item.commodity
            commodity.total_sales += item.count
            commodity.save()

            if not commodity_id:
                continue
            if commodity.id != commodity_id:
                continue

            if customer.is_distributor:
                continue
            customer.is_distributor = True
        customer.total_point += self.total_point
        customer.success_count += 1
        customer.save()

    def orderPay(self, openid, appid):
        if self.status != Order.WAIT_PAY:
            raise CustomError(u'订单非待付款状态，禁止付款！')
        if self.pay:
            pay_no = self.pay.no
            # 先查询订单状态
            checkRexponse = WeChatResponse(appid)
            total_fee = checkRexponse.OrderQuery(pay_no)
            if int(total_fee) == int(self.total_amount):
                wechatpay = WechatPay(appid)
                wechatpay.unifiedOrder(pay_no, self.total_amount, openid)
                data = wechatpay.getAppString()
                return data
            self.pay.payClosed()

    def orderPayConfirm(self):
        self.status = Order.WAIT_DISPATCH
        self.save()

        # 购买指定的商品 成为分销商
        commodity_id = Config.get_commodity()
        point_rule = Config.get_value(Config.KEY_POINT_RULE)
        customer = Customer.objects.filter(id=self.customer.id).first()

        detail = OrderDetails.objects.filter(order=self)
        for item in detail:
            commodity = item.commodity
            commodity.total_sales += item.count
            commodity.save()

            if not commodity_id:
                continue
            if commodity.id != commodity_id:
                continue
            if customer.is_distributor:
                continue
            customer.is_distributor = True
        customer.success_count += 1
        customer.total_amount += self.total_amount
        customer.total_point += self.total_point
        customer.save()


class OrderDetails(models.Model):

    order = models.ForeignKey(Order, verbose_name=u'订单', on_delete=models.PROTECT)
    commodity = models.ForeignKey(Commodity, verbose_name=u'商品', on_delete=models.PROTECT)
    price = models.BigIntegerField(verbose_name=u'价格', null=True, default=0)
    point = models.IntegerField(verbose_name=u'积分', null=True, default=0)
    count = models.IntegerField(verbose_name=u'数量', null=True, default=0)
    amount = models.BigIntegerField(verbose_name=u'总金额', null=True, default=0)
    point_amount = models.IntegerField(verbose_name=u'总积分', null=True, default=0)

    class Meta:
        db_table = u'order_details'
        verbose_name = u'订单明细'
        ordering = ('-id', )
        default_permissions = ()
        permissions = []
