# coding=utf-8
# create by oldman at 2017/11/3
import datetime
import json

from django.db.models import Q
from gm_dataquery.dataquery import DataBuilder, DataSQLQuery
from gm_types.doctor import DOCTOR_BILL_TYPE, DOCTOR_BILLAPPLY_STATUS, BILL_REFUSE_REASON, DOCTOR_EXPRESS_COMPANY
from gm_dataquery.db import DB

from api.models import BuDan, BDTransferMonthToBudan, BDTransferMonth, BDTransferApplyRecord
from hippo.models.bill import BillApplyRecord, BillApplyReopenRecord, BillIdToBillApply, BillToTransferBudan
from rpc.decorators import bind
from rpc.exceptions import GaiaRPCFaultException
from gm_types.error import ERROR
from gm_types.doctor import DOCTOR_BILL_CLASS
from django.db import transaction
from pay.models.statementall import StatementAll


class BillApplyRecordDB(DataBuilder):
    def getval_id_check(self, obj):
        return obj.id

    def getval_finance_info(self, obj):
        return json.loads(obj.snapshot).get('finance_info')['bill_header'] + ',' + \
               json.loads(obj.snapshot).get('finance_info')['receiver_address']

    def getval_statement_date(self, obj):
        bill_ids = json.loads(obj.snapshot).get('statement_ids', [])
        return u','.join([str(StatementAll.objects.get(id=bill_id).statement_date) for bill_id in bill_ids])

    def getval_rechange_ids(self, obj):
        bill_ids = json.loads(obj.snapshot).get('rechange_ids', [])
        return bill_ids

    def getval_budan_ids(self, obj):
        budan_ids = u','.join(BillToTransferBudan.objects.filter(billapplyrecord_id=obj.id).values_list('budan_id', flat=True))
        return budan_ids

    def getval_fill_amount(self, obj):
        fill_amount = 0
        budan_ids = list(BillToTransferBudan.objects.filter(billapplyrecord_id=obj.id).values_list('budan_id', flat=True))
        for budan_id in budan_ids:
            fill_amount += BuDan.objects.get(id=budan_id).payment
        return fill_amount

    def getval_is_finished(self, obj):
        budan_ids = list(BillToTransferBudan.objects.filter(billapplyrecord_id=obj.id).values_list('budan_id', flat=True))
        has_paids = BDTransferMonthToBudan.objects.filter(budan_id__in=budan_ids).values_list("has_paid", flat=True)
        return u'是' if all(has_paids) else u'否'

    def getval_bill_header(self, obj):
        return json.loads(obj.snapshot).get('finance_info')['bill_header']

    def getval_bill_type(self, obj):
        return DOCTOR_BILL_TYPE.getDesc(obj.bill_type)

    def getval_status_desc(self, obj):
        if obj.status == DOCTOR_BILLAPPLY_STATUS.REJECT:
            if obj.reason == BILL_REFUSE_REASON.OTHERS:
                return obj.more_reason
            return BILL_REFUSE_REASON.getDesc(obj.reason)
        else:
            return DOCTOR_BILLAPPLY_STATUS.getDesc(obj.status)

    def getval_bill_id(self, obj):
        return u','.join([item.bill_id for item in obj.applytobillids.all()])

    def getval_c_bill_id(self, obj):
        # 两个页面重复使用bill_id, 下面过滤出现的问题
        return u','.join([item.bill_id for item in obj.applytobillids.all()])

    def getval_r_bill_id(self, obj):
        return u','.join([item.bill_id for item in obj.applytobillids.all()])

    def getval_express_company(self, obj):
        return DOCTOR_EXPRESS_COMPANY.getDesc(obj.express_company)

    def getval_express_company_id(self, obj):
        if not obj.express_company:
            return 5
        return obj.express_company

    def getval_bill_type_id(self, obj):
        return obj.bill_type

    def getval_add_bills(self, obj):
        if obj.status == DOCTOR_BILLAPPLY_STATUS.SUCCESS and not obj.applytobillids.all().exists():
            return 1
        else:
            return 2

    def getval_add_express(self, obj):
        if obj.status == DOCTOR_BILLAPPLY_STATUS.SUCCESS and obj.express_company is None and \
                        obj.bill_type in [DOCTOR_BILL_TYPE.GENERAL, DOCTOR_BILL_TYPE.SPECIAL]:
            return 1
        else:
            return 2

    def getval_operate(self, obj):
        # 不要删除!!!
        return ''

    def getval_reopen_reason(self, obj):
        return BillApplyReopenRecord.objects.filter(reopenrecords_id=obj.id).last().reopen_reason

@DB
class BillApplyRecordDQ(DataSQLQuery):
    model = BillApplyRecord
    data_model = BillApplyRecordDB
    distinct = True

    def filter_created_time(self, srch_key, srch_val, regex=False):
        return self._qry_time_range(srch_key, srch_val, regex)

    def filter_bill_time(self, srch_key, srch_val, regex=False):
        return self._qry_time_range(srch_key, srch_val, regex)

    def filter_rechange_ids(self, srch_key, srch_val, regex=False):
        return Q(recordtorechanges__adrechange_id=srch_val)

    def filter_budan_ids(self, srch_key, srch_val, regex=False):
        return Q(recordtobudans__budan__id=srch_val)

    def filter_category(self, srch_key, srch_val, regex=False):
        return Q(category=int(srch_val))

    def filter_bill_id(self, srch_key, srch_val, regex=False):
        srch_val = bool(int(srch_val))
        billapplyrecord_ids = list(set(BillIdToBillApply.objects.filter(
            Q(billapplyrecord__category=DOCTOR_BILL_CLASS.COMMISSION) & (~Q(bill_id=''))
        ).values_list('billapplyrecord', flat=True)))
        q = Q(id__in=billapplyrecord_ids) if srch_val else ~Q(id__in=billapplyrecord_ids)
        return q

    def filter_c_bill_id(self, srch_key, srch_val, regex=False):
        srch_val = bool(int(srch_val))
        billapplyrecord_ids = list(set(BillIdToBillApply.objects.filter(
            Q(billapplyrecord__category=DOCTOR_BILL_CLASS.RECHANGE) & (~Q(bill_id=''))
        ).values_list('billapplyrecord', flat=True)))
        q = Q(id__in=billapplyrecord_ids) if srch_val else ~Q(id__in=billapplyrecord_ids)
        return q

    def filter_r_bill_id(self, srch_key, srch_val, regex=False):
        srch_val = bool(int(srch_val))
        billapplyrecord_ids = list(set(BillIdToBillApply.objects.filter(
            Q(billapplyrecord__category=DOCTOR_BILL_CLASS.BUDAN) & (~Q(bill_id=''))
        ).values_list('billapplyrecord', flat=True)))
        q = Q(id__in=billapplyrecord_ids) if srch_val else ~Q(id__in=billapplyrecord_ids)
        return q

    def getval_is_finished(self):
        not_filled_up, filled_up = [], []
        bill_all = BillApplyRecord.objects.all()
        for i in bill_all:
            budan_ids = list(BillToTransferBudan.objects.filter(billapplyrecord_id=i.id).values_list('budan_id', flat=True))
            has_paids = BDTransferMonthToBudan.objects.filter(budan_id__in=budan_ids).values_list("has_paid", flat=True)
            if all(has_paids):
                filled_up.append(i.id)
            else:
                not_filled_up.append(i.id)
        return filled_up, not_filled_up

    def filter_is_finished(self, srch_key, srch_val, regex=False):
        srch_val = bool(int(srch_val))
        filled_up, not_filled_up = self.getval_is_finished()
        q = Q(id__in=filled_up) if srch_val else Q(id__in=not_filled_up)
        return q

    def filter_express_id(self, srch_key, srch_val, regex=False):
        srch_val = not bool(int(srch_val))
        q = Q(express_id__isnull=srch_val)
        if srch_val:
            q |= Q(express_id='')
        else:
            q &= ~Q(express_id='')
        return q

    def update(self, updates, **kwargs):
        express_company = updates.pop('express_company_id')
        express_id = updates.get('express_id')
        reopen_reason = updates.pop('reopen_reason', None)
        bill_id = updates.pop('bill_id', None)
        bill_type = updates.pop('bill_type_id')
        updates.update({"express_company": express_company, 'bill_type': bill_type, 'bill_id': bill_id})

        if all([bill_type == str(DOCTOR_BILL_TYPE.ELECTRONIC), any([express_company != str(DOCTOR_EXPRESS_COMPANY.DEFAULT), express_id])]):
            raise GaiaRPCFaultException(ERROR.UNIVERSAL, '电子发票, 请勿填写快递公司和快递单号', data=None)

        if all([bill_type != str(DOCTOR_BILL_TYPE.ELECTRONIC), express_company == str(DOCTOR_EXPRESS_COMPANY.DEFAULT)]):
            raise GaiaRPCFaultException(ERROR.UNIVERSAL, '非电子发票，请正确填写快递公司', data=None)

        if bill_type != str(DOCTOR_BILL_TYPE.ELECTRONIC):
            updates.update({'express_id': express_id})

        self.model.objects.update_or_create(pk=kwargs['id'], defaults=updates)
        BillIdToBillApply.objects.filter(billapplyrecord_id=kwargs['id']).delete()
        bills = updates.get('bill_id').strip().split(',')
        [BillIdToBillApply.objects.get_or_create(billapplyrecord_id=kwargs['id'], bill_id=item) for item in bills]
        BillApplyReopenRecord.objects.filter(reopenrecords_id=kwargs['id']).update(status=False)
        BillApplyReopenRecord.objects.get_or_create(reopenrecords_id=kwargs['id'], reopen_reason=reopen_reason, status=True, **updates)
        self.model.objects.filter(id=kwargs['id']).update(remark=reopen_reason)


class BillApplyReopenRecordDB(DataBuilder):
    def getval_status(self, obj, need_escape=False):
        if obj.status:
            return '<span style="color:red;">生效中<span>'
        else:
            return '作废'

    def getval_express_company(self, obj):
        if int(obj.bill_type) == DOCTOR_BILL_TYPE.ELECTRONIC:
            return ''
        else:
            return obj.bill_type


@DB
class BillApplyReopenRecordDQ(DataSQLQuery):
    model = BillApplyReopenRecord
    data_model = BillApplyReopenRecordDB


@bind('gaia/db/billapplyrecord_excel_update/update')
def billapplyrecord_excel_update(updates, **kwargs):
    """
    佣金商桥
    """
    id = updates.get('id', None)
    bill_type = updates.get('bill_type', None)
    express_company = updates.pop('express_company', None)
    express_id = updates.pop('express_id', None)
    bill_id = updates.pop('bill_id')
    if not id:
        raise GaiaRPCFaultException(ERROR.UNIVERSAL, '发票申请ID是必填项', data=None)
    obj = BillApplyRecord.objects.filter(id=id)
    if not obj:
        raise GaiaRPCFaultException(ERROR.UNIVERSAL, '发票申请ID不存在', data=None)
    if BillApplyRecord.objects.filter(id=id).first().status == DOCTOR_BILLAPPLY_STATUS.REJECT:
        raise GaiaRPCFaultException(ERROR.UNIVERSAL, '驳回状态的发票申请不可导入开票信息', data=None)
    if not updates.get('amount'):
        raise GaiaRPCFaultException(ERROR.UNIVERSAL, '发票金额是必填项', data=None)
    if not updates.get('bill_type'):
        raise GaiaRPCFaultException(ERROR.UNIVERSAL, '发票类型是必填项', data=None)
    if not bill_id:
        raise GaiaRPCFaultException(ERROR.UNIVERSAL, '发票编号是必填项', data=None)

    if all([bill_type == str(DOCTOR_BILL_TYPE.ELECTRONIC),
            any([express_company, express_id])]):
        raise GaiaRPCFaultException(ERROR.UNIVERSAL, '电子发票, 请勿填写快递公司和快递单号', data=None)

    if all([bill_type != str(DOCTOR_BILL_TYPE.ELECTRONIC), any([not express_company, not str(express_company) in ['0', '1', '2', '3', '4', '5', '6']])]):
        raise GaiaRPCFaultException(ERROR.UNIVERSAL, '非电子发票，请正确填写快递公', data=None)
    if all([bill_type != str(DOCTOR_BILL_TYPE.ELECTRONIC), not express_id]):
        raise GaiaRPCFaultException(ERROR.UNIVERSAL, '非电子发票，请正确填写快递单号', data=None)
    if bill_type != str(DOCTOR_BILL_TYPE.ELECTRONIC):
        updates.update(express_company=int(express_company), express_id=express_id)
    else:
        obj.update(express_company=20, express_id=None)
    updates['status'] = 0
    updates['bill_time'] = datetime.datetime.today()
    obj.update(**updates)
    BillIdToBillApply.objects.filter(billapplyrecord_id=id).delete()
    bills = bill_id.strip().split(',')
    [BillIdToBillApply.objects.get_or_create(billapplyrecord_id=id, bill_id=item) for item in bills]
    BillApplyReopenRecord.objects.filter(reopenrecords_id=id).update(status=False)
    defaults = {'bill_id': bill_id, 'bill_type': bill_type}
    defaults['express_company'] = updates.get('express_company')
    defaults['express_id'] = updates.get('express_id')
    BillApplyReopenRecord.objects.get_or_create(defaults=defaults, reopenrecords_id=id, reopen_reason=updates.get('remark', ''), status=True)


