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

import json
import math

from datetime import datetime
from django.db import models
from django.db.models import Sum
from gm_types.trade import STATEMENT_STATUS
from gm_types.gaia import ACCOUNT_TYPE, DOCTOR_TYPE, COUPON_TYPES
from api.models import Doctor
from api.models import Order
from api.models import Province, City
from pay.manager.statement_manager import StatementManager, HistoryStatementManager
from rpc.tool.dict_mixin import to_dict


class Statement(models.Model):
    class Meta:
        db_table = 'pay_statement'
        app_label = 'pay'
        unique_together = ('doctor', 'statement_date')

    id = models.CharField(max_length=15, verbose_name='结算单号', primary_key=True)
    doctor = models.ForeignKey(Doctor, verbose_name='结算对象医生')
    status = models.IntegerField(choices=STATEMENT_STATUS, default=STATEMENT_STATUS.APPLIED)
    orders = models.ManyToManyField(Order, verbose_name='关联订单', through='OrderStatementRelationship',
                                    related_name='statement')
    # 发票计算专用，order.servicesnapshot.pre_payment_price的累加
    total_real_prepay = models.FloatField(verbose_name='美购中显示的预付款金额', default=0)
    # 发票计算专用，order.discount的累加
    total_discount = models.FloatField(verbose_name='抽成总额', default=0)

    original_amount = models.FloatField(verbose_name='应结预付款总额', default=0)  # 总预付款减总抽成
    settle_amount = models.FloatField(verbose_name='结算金额', default=0)  # must be positive
    pos_back = models.FloatField('pos机回款金额', default=0.00)  # must be positive
    poundage_rate = models.FloatField(verbose_name='手续费率', default=0)  # 以后百分比默认存百分比
    created_at = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
    updated_at = models.DateTimeField(auto_now=True, verbose_name=u'最后一次修改时间')
    statement_date = models.IntegerField(verbose_name='结算年月', null=False)
    merchant_confirm_time = models.DateTimeField(verbose_name='商户确认时间', null=True)
    settle_time = models.DateTimeField(verbose_name='财务结算时间', null=True)
    check_snapshot = models.TextField(default='', verbose_name='医生确认时快照')
    settle_snapshot = models.TextField(default='', verbose_name='财务打款时快照')
    sub_data = models.TextField('分类详细信息', default='')

    # 10月(包括)之前的对战单
    history_objects = HistoryStatementManager()
    objects = StatementManager()

    @property
    def new_total_settle_amount(self):
        """总结算单概念之后, 美购订单, 医生的结算单总额"""
        return self.original_amount + self.pos_back

    @property
    def fenxiao_service_amount(self):
        """分销美购结算总金额"""
        origin_data = json.loads(self.sub_data)
        self.__dict__['fenxiao_service_amount'] = origin_data['fenxiao_amount']
        self.__dict__['normal_service_amount'] = origin_data['normal_amount']
        return self.__dict__['fenxiao_service_amount']

    @property
    def normal_service_amount(self):
        """普通美购结算总金额"""
        origin_data = json.loads(self.sub_data)
        self.__dict__['fenxiao_service_amount'] = origin_data['fenxiao_amount']
        self.__dict__['normal_service_amount'] = origin_data['normal_amount']
        return self.__dict__['normal_service_amount']

    # 如果有新字段加入, 不要忘记要加入@propery snapshot
    def get_snapshot(self):
        # return a json
        return json.dumps(dict(
            id=self.id,
            doctor_id=self.doctor_id,
            order_ids=[order.id for order in self.orders.all()],
            original_amount=self.original_amount,
            settle_amount=self.settle_amount,
            poundage_rate=self.poundage_rate,
            # account=to_dict(self.account),  新的对账单合并后不会在美购对账单上记录账户的信息
        )
        )

    def data(self):
        return {
            'id': self.id,
            'is_officer': self.doctor.doctor_type == DOCTOR_TYPE.OFFICER,
            'statement_date': self.statement_date,
            'settled_num': self.settled_num,
            'order_total_price': self.order_total_price,
            'settle_price': self.settle_price,
            'status': self.status,
        }

    @property
    def order_total_price(self):
        return self.orders.aggregate(sum=Sum('service_price')).get('sum') or 0

    @property
    def discount_sum(self):
        discount_list = [order.discount for order in self.orders.all()]
        return sum(discount_list)

    @property
    def feededuction_sum(self):
        # 补扣款总和   补款为正 扣款为负
        return -round(self.fee_deduction.aggregate(**{'feededuction_sum': Sum('value')}).get('feededuction_sum') or 0,
                      2)

    @property
    def settle_price(self):
        # 结算金额
        return round(self.original_amount + self.feededuction_sum - self.poundage + self.pos_back, 2)

    @property
    def poundage(self):
        # 手续费
        return math.ceil(abs((self.original_amount + self.feededuction_sum) * self.poundage_rate)) / 100

    @property
    def settled_num(self):
        # 已验证订单数
        return self.orders.count()

    @property
    def account_has_changed(self):
        doc_account = self.doctor.merchant.account
        stm_account = getattr(self, 'account', None)
        if not stm_account and doc_account:
            return True
        check_fields = ['account_name', 'account_number', 'bank']
        not_changed = all(
            [getattr(stm_account, field) == getattr(doc_account, field)
             for field in check_fields]
        )
        return not not_changed

    def get_account(self):
        # if self.status in [STATEMENT_STATUS.SETTLED, STATEMENT_STATUS.DEFEAT]:
        #     account = getattr(self, 'account', None)
        #     if self.status == STATEMENT_STATUS.DEFEAT and self.account_has_changed:
        #         account = self.doctor.merchant.account
        # else:
        #     account = self.doctor.merchant.account
        account = self.account
        return account


class StatementAccount(models.Model):
    class Meta:
        verbose_name = '结算账户'
        db_table = 'pay_statementaccount'
        app_label = 'pay'

    statement = models.OneToOneField(Statement, verbose_name=u'关联对账单', related_name='account')
    province = models.ForeignKey(Province, null=True, blank=True)
    city = models.ForeignKey(City, null=True, blank=True)
    bank = models.CharField('开户银行', max_length=30)
    subbranch = models.CharField('支行/分行', max_length=100)
    account_name = models.CharField('户名', max_length=100)
    account_number = models.CharField('账号', max_length=50)
    account_type = models.IntegerField('开户类型', choices=ACCOUNT_TYPE, default=ACCOUNT_TYPE.BANK)


class OrderStatementRelationship(models.Model):
    class Meta:
        db_table = 'pay_orderstatementrelationship'
        app_label = 'pay'

    statement = models.ForeignKey(Statement, verbose_name='关联医生对账单')
    order = models.OneToOneField(Order, verbose_name='关联订单')
    installment = models.BooleanField(default=False, verbose_name='尾款分期(任买)')

    @property
    def order_info(self):
        coupon_info = {x['coupon_type']: x for x in self.order.get_order_coupon_infos()}
        settle_price = coupon_info.get(COUPON_TYPES.PLATFORM, {}).get('coupon_doctor_value', 0)
        servicesnapshot = self.order.servicesnapshot
        merchant_deduction = 0
        if servicesnapshot.coupon_info_id:
            merchant_deduction = servicesnapshot.coupon_doctor_value
        return {
            'id': self.order.id,
            'doctor_name': self.order.service.doctor.name,
            'service_name': json.loads(self.order.service_snapshot).get('name'),
            'order_multiattribute': self.order.order_multiattribute,
            'total_num': json.loads(self.order.service_snapshot).get('gengmei_price'),
            'pre_payment_price': json.loads(self.order.service_snapshot).get('pre_payment_price'),
            'settle_price': self.order.servicesnapshot.pre_payment_price - self.order.discount - settle_price,
            'validate_time': self.order.validate_time.strftime("%Y-%m-%d %H:%M:%S"),
            #新增抽成佣金、商家承担美券金额、美分抵扣计算
            'discount': self.order.discount,
            'merchant_deduction': merchant_deduction,
            'service_points_deduction': self.order.points_deduction
        }


class FeeDeduction(models.Model):
    class Meta:
        db_table = 'pay_feededuction'
        app_label = 'pay'

    statement = models.ForeignKey(Statement, verbose_name='关联的结账单', related_name='fee_deduction')
    value = models.FloatField(verbose_name='扣除费用')
    comment = models.CharField(verbose_name='扣费说明', max_length=100)


class StatementRefusedRecord(models.Model):
    class Meta:
        verbose_name = '对账单医生驳回记录'
        db_table = 'pay_statementrefusedrecord'
        app_label = 'pay'

    statement = models.ForeignKey(Statement, related_name='refused_records')
    reason = models.CharField(max_length=140, help_text=u'申诉理由')
    create_time = models.DateTimeField(auto_now_add=True)
