# coding=utf-8
# create by oldman at 2017/10/31
import json

from django.db import models
from django.db.backends.mysql.base import IntegrityError
from django.db.models import Sum
from pay.tool import random_tool
from rpc.tool.dict_mixin import to_dict
from gm_types.gaia import ACCOUNT_TYPE
from gm_types.trade import STATEMENT_STATUS, STATEMENT_OPERATION_TYPE, OPERATION_ROLE

from hippo.models import Doctor, Person, Province, City
from maidan.models import MaidanStatement
from pay.models import Statement


class StatementAll(models.Model):
    class Meta:
        db_table = 'pay_statementall'
        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)
    settle_amount = models.FloatField(verbose_name='医生确认之后,记录的总结算额', default=0)  # must be positive
    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)
    service_statement = models.OneToOneField(Statement, verbose_name=u'美购结算单')
    maidan_statement = models.OneToOneField(MaidanStatement, verbose_name=u'买单结算单', null=False)
    check_snapshot = models.TextField(default='', verbose_name='医生确认时快照')
    settle_snapshot = models.TextField(default='', verbose_name='财务打款时快照')
    created_at = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
    updated_at = models.DateTimeField(auto_now=True, verbose_name=u'最后一次修改时间')

    def save(self, *args, **kwargs):
        if not self.pk:
            self.id = random_tool.generate_id(id_length=12)
        while True:
            try:
                super(StatementAll, self).save(*args, **kwargs)
                break
            except IntegrityError as e:
                if "PRIMARY" in e[1]:  # 主键重复
                    self.id = random_tool.generate_id(id_length=12)
                else:
                    raise

    @property
    def total_settle_amount(self):
        """总的结算单额,元"""
        return (self.service_statement.new_total_settle_amount * 10 * 10 + self.maidan_statement.settle_amount_cent + self.feededuction_sum * 10 * 10) / 100

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

    @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):
        from hippo.models.merchant import MerchantAccount
        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
        elif MerchantAccount.objects.filter(merchant_id=self.doctor.merchant.id):
            account = self.doctor.merchant.account
        else:
            account = None
        return account

    # 如果有新字段加入, 不要忘记要加入@propery snapshot
    def get_snapshot(self):
        # return a json
        return json.dumps(dict(
            id=self.id,
            doctor_id=self.doctor_id,
            total_settle_amount=self.total_settle_amount,
            maidan_statement_id=self.maidan_statement.id,
            service_statement_id=self.service_statement.id,
            account=to_dict(self.account),
        )
        )


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

    statementall = models.OneToOneField(StatementAll, 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, null=True)
    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 StatementAllOperation(models.Model):
    class Meta:
        db_table = 'pay_statementalloperation'
        app_label = 'pay'

    statementall = models.ForeignKey(StatementAll, verbose_name='关联对账单')
    operator = models.ForeignKey(Person, null=True)
    optype = models.IntegerField(verbose_name='操作类型', choices=STATEMENT_OPERATION_TYPE)
    role = models.IntegerField(choices=OPERATION_ROLE)
    operate_at = models.DateTimeField(null=True, blank=True, verbose_name='操作时间', auto_now_add=True)
    content = models.CharField(null=True, blank=True, verbose_name='备注信息等(申述理由，)', max_length=300)


class FeeDeductionAll(models.Model):
    class Meta:
        db_table = 'pay_feedeductionall'
        app_label = 'pay'

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