package com.ag.account.detail;

import com.ag.account.feeUtil.FormulaUtil;
import com.ag.account.feeUtil.NotesUtil;
import com.ag.account.feeUtil.ReductionUtil;
import com.ag.entity.account.FeeDetail;
import com.ag.entity.account.vo.BizVO;
import com.ag.entity.fee.BaseChargingItem;
import com.ag.entity.fee.ContractItem;
import com.ag.entity.fee.face.ICondition;
import com.ag.entity.fee.face.SourceProperty;
import com.ag.entity.fee.vo.TariffVO;
import com.ag.util.StrUtil;
import com.ag.util.TimeUtil;
import com.ag.util.UUIDUtil;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeanUtils;

import java.util.Date;

/**
 * Created by Administrator on 2017/6/19 0019.
 */
public abstract class AccountDetail {
    protected final Log logger = LogFactory.getLog(AccountDetail.class);

   

    /******************************* start ***********************************/


    public void getFeeDetail(BizVO bizVO, SourceProperty source) {
        calcBefore(bizVO, source);
        createFeeDetails(bizVO, source);
        calcByTariff(source);
        if (source.getPayDetail() != null){
            bizVO.getDetails().add(source.getPayDetail());
            calcByUnit(bizVO, source, source.getPayDetail());//计算公式
            calcByDiscount(bizVO, source, source.getPayDetail());//优惠减免
        }
        if (source.getReceiveDetail() != null){
            bizVO.getDetails().add(source.getReceiveDetail());
            calcByUnit(bizVO, source, source.getReceiveDetail());//计算公式
            calcByDiscount(bizVO, source, source.getReceiveDetail());//优惠减免
        }
        convertCurrentRatio(source);
    }

    /**
     * 费率转换
     * 应收应付不同币种，费率维护按应收维护，应付金额=应收金额/兑换比例
     * 如果property里存在兑换比例属性CURRENCY_RATIO，以property兑换比例为准
     * @param source
     */
    private void convertCurrentRatio(SourceProperty source) {
        if (source.getPayDetail() == null || source.getReceiveDetail() == null){
            return;
        }
        if (source.getContractItem().getPayCurrency() == null || source.getContractItem().getReceiveCurrency() == null){
            return;
        }
        if (source.getContractItem().getPayCurrency().equals( source.getContractItem().getReceiveCurrency())){
            return;
        }
        Double ratio = 0d;
        if (source.getContractItem().getCurrencyRatio() != null){
            ratio = source.getContractItem().getCurrencyRatio();
        }
        if (source.getProperty().get(ICondition.CURRENCY_RATIO) != null){
            ratio = source.getProperty().getDouble(ICondition.CURRENCY_RATIO);
        }
        if (ratio == 0d){
            return;
        }
        FeeDetail pay = source.getPayDetail();
        pay.setCurrency(source.getContractItem().getPayCurrency());
        pay.setStRate(pay.getStRate() / ratio);
        pay.setActualRate(pay.getActualRate() / ratio);
        pay.setStMoney(pay.getStMoney() / ratio);
        pay.setFinalMoney(pay.getFinalMoney() / ratio);

    }

    /**
     * 按费率规则修改计费明细
     */
    private void calcByTariff(SourceProperty source) {
        ContractItem contractItem = source.getContractItem();
        JSONObject json = source.getProperty();
        TariffVO tariffVO = source.getTariffVO();
        if (!StrUtil.isEmpty(tariffVO.getReceiveCode())){
            if (source.getReceiveDetail() == null){
                FeeDetail detail = new FeeDetail();
                BeanUtils.copyProperties(source.getPayDetail(), detail);
                detail.setId(UUIDUtil.getUUID());
                detail.setPayReceiveType("0");
                source.setReceiveDetail(detail);
            }
            source.getReceiveDetail().setClientCode(json.getString(tariffVO.getReceiveCode()));
        }/*else {
            source.setReceiveDetail(null);
        }*/
        if (!StrUtil.isEmpty(tariffVO.getPayCode())){
            if (source.getPayDetail() == null){
                FeeDetail detail = new FeeDetail();
                BeanUtils.copyProperties(source.getReceiveDetail(), detail);
                detail.setId(UUIDUtil.getUUID());
                detail.setPayReceiveType("1");
                source.setPayDetail(detail);
            }
            source.getPayDetail().setClientCode(json.getString(tariffVO.getPayCode()));
        } /*else {
            source.setPayDetail(null);
        }*/
        if (tariffVO.getPayRate() != null && source.getPayDetail() != null){
            source.getPayDetail().setStRate(tariffVO.getPayRate());
            source.getPayDetail().setActualRate(tariffVO.getPayRate());
            setMoney(source.getPayDetail(), contractItem);
        }
        if (tariffVO.getReceiveRate() != null && source.getReceiveDetail() != null){
            source.getReceiveDetail().setStRate(tariffVO.getReceiveRate());
            source.getReceiveDetail().setActualRate(tariffVO.getReceiveRate());
            setMoney(source.getReceiveDetail(), contractItem);
        }
        if (!StrUtil.isEmpty(tariffVO.getPayCurrency()) && source.getPayDetail() != null){
            source.getPayDetail().setCurrency(tariffVO.getPayCurrency());
        }
        if (!StrUtil.isEmpty(tariffVO.getReceiveCurrency()) && source.getReceiveDetail() != null){
            source.getReceiveDetail().setCurrency(tariffVO.getReceiveCurrency());
        }
        if (!StrUtil.isEmpty(tariffVO.getPayMan()) && source.getPayDetail() != null){
            source.getPayDetail().setClientCode(tariffVO.getPayMan());
        }
        if (!StrUtil.isEmpty(tariffVO.getReceiveMan()) && source.getReceiveDetail() != null){
            source.getReceiveDetail().setClientCode(tariffVO.getReceiveMan());
        }
    }


    /**
     * 计费前数据处理
     */
    protected void calcBefore(BizVO bizVO, SourceProperty property){
    }

    /***
     * 按计费单位算金额
     */
    protected void calcByUnit(BizVO bizVO, SourceProperty property, FeeDetail detail){
    }

    /**
     * 优惠减免
     */
    protected void calcByDiscount(BizVO bizVO, SourceProperty source, FeeDetail detail) {
        ReductionUtil.calcByDiscount(source.getProperty(), detail);
    }


    protected void createFeeDetails(BizVO bizVO, SourceProperty source) {
        ContractItem contractItem = source.getContractItem();
        TariffVO tariffVO = source.getTariffVO();
        JSONObject property = source.getProperty();
        FeeDetail fee = new FeeDetail();
        fee.setTenancyId(bizVO.getTenancyId());
        fee.setBussinessCode(source.getBizId());
        fee.setJobFinishDate(TimeUtil.getTimestamp(source.getBizTime()));
        fee.setJobCategoryCode(source.getBizType());

        fee.setContractId(contractItem.getContractId());
        fee.setFeeGroupId(contractItem.getCategoryId());
        fee.setFeeListId(contractItem.getItemId());
        fee.setCurrency(StrUtil.isEmpty(contractItem.getCurrency()) ? ICondition.DEFAULT_CURRENCY : contractItem.getCurrency());
        fee.setInvoiceType(contractItem.getInvoiceType());
        fee.setUnitId(contractItem.getUnit());
        fee.setEnabled(contractItem.getEnabled());
        fee.setSourceItemCode(contractItem.getSourceItemCode());

        BaseChargingItem baseItem = bizVO.getItemMap().get(contractItem.getItemId());
        fee.setOriginalItemName(baseItem.getDescription());
        fee.setItemCode(baseItem.getItemCode());

        //fee.setAuditFlag(0);
        fee.setCreatedBy(bizVO.getReqSource().getOperMan());
        fee.setCreatedOn(new Date());
        fee.setUpdatedBy(bizVO.getReqSource().getOperMan());
        fee.setUpdatedOn(new Date());
        //fee.setCancelFlag(0);
        //fee.setSettleStatus(0);

        fee.setStRate(tariffVO.getRate());//标准费率
        fee.setActualRate(fee.getStRate());//执行费率
        FormulaUtil.execute(source, contractItem, fee);//获取表达式费率（更新执行费率）

        fee.setQuantity(getQuantity(property, contractItem));//数量,默认1d
        fee.setDiscount(getDiscount(property));//折扣,默认100d
        fee.setSettleDays(getSettleDays(bizVO));//结算天,默认1
        setMoney(fee, contractItem);
        if (!StrUtil.isEmpty(tariffVO.getCurrency())){
            fee.setCurrency(tariffVO.getCurrency());
        }
        fee.setTariffNote(tariffVO.getNotes());

        NotesUtil.setFeeByTariffScription(fee, source);


        //应收费用明细
        if (!StrUtil.isEmpty(contractItem.getReceiveCode())){
            fee.setId(UUIDUtil.getUUID());
            fee.setPayReceiveType("0");
            if (StrUtil.isEmpty(contractItem.getReceiveMan())) {
                fee.setClientCode(getReckoner(property, contractItem.getReceiveCode()));
            }else {
                fee.setClientCode(contractItem.getReceiveMan());
            }
            if (!StrUtil.isEmpty(contractItem.getReceiveCurrency())) {
                fee.setCurrency(contractItem.getReceiveCurrency());
            }
            source.setReceiveDetail(fee);
        }
        //应付费用明细
        if (!StrUtil.isEmpty(contractItem.getPayCode())){
            FeeDetail payDetail = new FeeDetail();
            BeanUtils.copyProperties(fee, payDetail);
            payDetail.setId(UUIDUtil.getUUID());
            payDetail.setPayReceiveType("1");
            if (StrUtil.isEmpty(contractItem.getPayMan())) {
                payDetail.setClientCode(getReckoner(property, contractItem.getPayCode()));
            }else {
                payDetail.setClientCode(contractItem.getPayMan());
            }
            if (!StrUtil.isEmpty(contractItem.getPayCurrency())) {
                fee.setCurrency(contractItem.getPayCurrency());
            }
            source.setPayDetail(payDetail);
        }
    }

    protected String getReckoner(JSONObject property, String ownerCode) {
        return property.getString(ownerCode);
    }

    protected void setMoney(FeeDetail fee, ContractItem contractItem) {
        fee.setCalcMoney(fee.getActualRate() * fee.getQuantity()* fee.getDiscount()* fee.getSettleDays() / 100);
        fee.setStMoney(fee.getStRate() * fee.getQuantity() * fee.getDiscount() * fee.getSettleDays() / 100);
        fee.setFinalMoney(fee.getCalcMoney());
        if (contractItem.getAmountFormat() == null){
            return;
        }
        if (contractItem.getFormatUnit() == null){
            contractItem.setFormatUnit(0);
        }
        //进整
        if (contractItem.getAmountFormat() == 0) {
            fee.setCalcMoney(Math.ceil(fee.getCalcMoney()));
        }
        //四舍五入
        if (contractItem.getAmountFormat() == 1) {
            //元
            if (contractItem.getFormatUnit() == 0) {
                fee.setCalcMoney((double) Math.round(fee.getCalcMoney()));
            }
            //角
            if (contractItem.getFormatUnit() == 1) {
                fee.setCalcMoney((double) Math.round(fee.getCalcMoney() * 10) / 10);
            }
            //分
            if (contractItem.getFormatUnit() == 2) {
                fee.setCalcMoney((double) Math.round(fee.getCalcMoney() * 100) / 100);
            }
        }
        //去小数
        if (contractItem.getAmountFormat() == 2) {
            fee.setCalcMoney(Math.floor(fee.getCalcMoney()));
        }
        fee.setFinalMoney(fee.getCalcMoney());
    }

    protected Double getQuantity(JSONObject property, ContractItem contractItem){
        return 1d;

    }

    protected Double getDiscount(JSONObject property) {
        return 100d;
    }

    protected Integer getSettleDays(BizVO bizVO){
        return 1;
    }
}
