package com.brilliance.isc.common.fecism.calcfee.impl;

import com.brilliance.mda.runtime.mda.impl.Argument;
import com.brilliance.mda.runtime.mda.util.Dates;
import com.brilliance.mda.runtime.mda.util.Decimals;
import com.brilliance.mda.runtime.mda.util.MdaUtils;
import com.brilliance.mda.runtime.mda.util.Strings;
import com.brilliance.isc.bo.Cbb;
import com.brilliance.isc.common.cbsmod.service.CbsmodService;
import com.brilliance.isc.common.cbsmod.service.XrtmodService;
import com.brilliance.isc.common.codetable.service.CodetableService;
import com.brilliance.isc.common.component.DyncDaoService;
import com.brilliance.isc.common.fecism.calcfee.AbstractFeeCalculator;
import com.brilliance.isc.common.fecism.vo.CalcFeeRequest;
import com.brilliance.isc.common.fecism.vo.CalcFeeResponse;
import com.brilliance.isc.common.util.StringUtils;
import com.brilliance.isc.common.util.Utils;
import com.brilliance.isc.common.vo.SimpleModuleVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.Date;

//计算规则是M 信用证修改
@Component("M_FeeCalculator")
public class LcAmdFeeCalculator extends AbstractFeeCalculator {

    @Autowired
    private XrtmodService xrtmodService;

    @Autowired
    private CodetableService codetableService;

    @Autowired
    private CbsmodService cbsmodService;

    @Autowired
    private DyncDaoService dyncDaoService;

    @Override
    protected CalcFeeResponse calculate(CalcFeeRequest request) {
        //! 计算信用证修改手续费费用金额
        //!================================================
        //!参数：  line    -  要计算的费用行
        //!        relcur  -  基准币种
        //!        relamt  -  基准金额
        //!        feecur  -  费用币种
        //!返回值：费用金额
        //!================================================
        //手续费分两部分：
        //1.增额金额按照当前期限算出增额部分；
        //2.展期情况下，要按信用证余额和展期后多出的期限计算
        String feecur = request.getFeecur();
        String relcur = request.getRelcur();
        BigDecimal relamt = request.getRelAmt();
        CalcFeeResponse response = new CalcFeeResponse();
        buildInfdetstm(response, request.getRelcur(), request.getRelAmt());
        //费用计算细节
        String inftxt = buildInftxt(request);
        //inftxt += CR + Strings.getText("Calculation based on $1 i.e. $2 $3", codetableService.getTblLabel(request.getCalcbs(), "FECAMT"), request.getRelcur(), Utils.fmtAmount(request.getRelAmt(), request.getRelcur()));
        inftxt += CR + Strings.getText("计算基准为$1,金额 $2 $3", codetableService.getTblLabel(request.getCalcbs(), "CALCBS"), relcur, Utils.fmtAmount(relamt, relcur));
        inftxt += CR + Strings.getText("计费规则是千分率");
        boolean litameFlag = true;
        SimpleModuleVo linkModule = null;
        try {
            linkModule = Utils.toObject(SimpleModuleVo.class, request.getObjmod());
        } catch(Exception e) {
            linkModule = null;
        }
        if (linkModule == null) {
            litameFlag = false;
        } else if (StringUtils.isEmpty(linkModule.getObjinr()) || StringUtils.isEmpty(linkModule.getObjtyp())) {
            litameFlag = false;
        }
        Date date1 = request.getDat1();
        Date date2 = request.getDat2();
        int unt = request.getUnt();
        BigDecimal ogiamt = BigDecimal.ZERO;
        BigDecimal amt = BigDecimal.ZERO;
        if (litameFlag) {
            BigDecimal opnamt = BigDecimal.ZERO;
            Date date = Dates.add(Utils.getMaxDate(), -1);
            Cbb opn1 = new Cbb();
            cbsmodService.cbsGetBalance(opn1, linkModule.getObjtyp(), linkModule.getObjinr(), "OPN", "AMT1", date);
            if (opn1 != null) {
                opnamt = opnamt.add(opn1.getAmt());
            }
            Cbb opn2 = new Cbb();
            cbsmodService.cbsGetBalance(opn2, linkModule.getObjtyp(), linkModule.getObjinr(), "OPN", "AMT2", date);
            if (opn2 != null) {
                opnamt = opnamt.add(opn2.getAmt());
            }
            BigDecimal relFeecurAmt = relamt;
            //1.信用证余额与增额
            if (MdaUtils.compareTo(relcur, feecur) != 0) {
                BigDecimal xrtrelamt = xrtmodService.amtConvTypes(relcur, relamt, "M", feecur, "M", Dates.today());
                BigDecimal xrtopnamt = xrtmodService.amtConvTypes(relcur, opnamt, "M", feecur, "M", Dates.today());
                if (MdaUtils.compareTo(xrtrelamt, 0) > 0) {
                    inftxt += CR + Strings.getText("增额 $1 $2 converted to $3 $4", relcur, Utils.fmtAmount(relamt, relcur), feecur, Utils.fmtAmount(xrtrelamt, feecur));
                }
                relFeecurAmt = xrtrelamt;
                if (MdaUtils.compareTo(xrtopnamt, 0) > 0) {
                    inftxt += CR + Strings.getText("信用证余额 $1 $2 converted to $3 $4", relcur, Utils.fmtAmount(opnamt, relcur), feecur, Utils.fmtAmount(xrtopnamt, feecur));
                }
                opnamt = xrtopnamt;
            }
            BigDecimal ratuse = request.getRatcal();
            String pertyp = request.getPertyp();
            //计算费用份数 和 收费日期
            //否则根据份数算日期
            if (!MdaUtils.isEmpty(pertyp) && !"n".equals(request.getPertyp())) {
                if (date2 == null || "u".equals(request.getModflg()) || request.getGraceDays() != 0) {
                    //根据份数算日期 (非修改手续费情况)
                    if (date1 != null) {
                        date2 = Utils.calcDate(date1, unt, pertyp, "");
                    }
                } else {
                    //根据日期算份数
                    if (date1 != null && date2 != null) {
                        unt = Utils.calcUnt(date1, date2, pertyp);
                        //重新根据unt算日期
                        date2 = Utils.calcDate(date1, unt, pertyp, "");
                    }
                }
            }
            BigDecimal basis = new BigDecimal(1000);
            BigDecimal fecamt1 = BigDecimal.ZERO;
            BigDecimal fecamt2 = BigDecimal.ZERO;
            //增额部分计算费用
            Date oldmatdat = dyncDaoService.dyncReadFieldByInr(linkModule.getObjtyp(), linkModule.getObjinr(), "expdat");
            int perprv = Utils.calcUnt(date1, date2, pertyp);
            int oldperprv = Utils.calcUnt(date1, oldmatdat, pertyp);
            if (oldperprv < 1) {
                //开证手续费最小期限为1
                oldperprv = 1;
            }
            int addprv = Utils.calcUnt(Dates.today(), date2, pertyp);
            if (relamt.compareTo(BigDecimal.ZERO) > 0) {
                inftxt += CR + Strings.getText("开始计算增额 $1 $2 费用", feecur, Utils.fmtAmount(relFeecurAmt, feecur));
                inftxt += CR + Strings.getText("本次收取$1单元$2", unt, codetableService.getTblLabel(request.getFeecod(), "FEETXT"));
                if (addprv < request.getPermin()) {
                    addprv = request.getPermin();
                    inftxt += CR + Strings.getText("使用最小单元$1", addprv);
                }
                BigDecimal lftunt = new BigDecimal(addprv);
                int oldper = 0;
                BigDecimal tirunt = null;
                if (MdaUtils.compareTo(Decimals.add(lftunt, oldper), request.getPerbegtr5()) >= 0 && request.getPerbegtr5() != 0) {
                    tirunt = Decimals.add(Decimals.sub(Decimals.add(lftunt, oldper), request.getPerbegtr5()), 1);
                    tirunt = getMinimum(tirunt, lftunt);
                    BigDecimal feeamt = Decimals.div(Decimals.mul(relFeecurAmt, request.getPerrattr5()), basis);
                    feeamt = xrtmodService.amtRnd(feeamt, feecur);
                    feeamt = Decimals.mul(feeamt, tirunt);
                    fecamt1 = Decimals.add(fecamt1, feeamt);
                    inftxt += CR + Strings.getText("从第$1段开始使用费率$2,单元为$3,计算费用金额为$4",request.getPerbegtr5(), request.getPerrattr5(), tirunt, feeamt);
                    lftunt = Decimals.sub(lftunt, tirunt);
                }
                if (MdaUtils.compareTo(Decimals.add(lftunt, oldper), request.getPerbegtr4()) >= 0 && request.getPerbegtr4() != 0) {
                    tirunt = Decimals.add(Decimals.sub(Decimals.add(lftunt, oldper), request.getPerbegtr4()), 1);
                    tirunt = getMinimum(tirunt, lftunt);
                    BigDecimal feeamt = Decimals.div(Decimals.mul(relFeecurAmt, request.getPerrattr4()), basis);
                    feeamt = xrtmodService.amtRnd(feeamt, feecur);
                    feeamt = Decimals.mul(feeamt, tirunt);
                    fecamt1 = Decimals.add(fecamt1, feeamt);
                    inftxt += CR + Strings.getText("从第$1段开始使用费率$2,单元为$3,计算费用金额为$4",request.getPerbegtr4(), request.getPerrattr4(), tirunt, feeamt);
                    lftunt = Decimals.sub(lftunt, tirunt);
                }
                if (MdaUtils.compareTo(Decimals.add(lftunt, oldper), request.getPerbegtr3()) >= 0 && request.getPerbegtr3() != 0) {
                    tirunt = Decimals.add(Decimals.sub(Decimals.add(lftunt, oldper), request.getPerbegtr3()), 1);
                    tirunt = getMinimum(tirunt, lftunt);
                    BigDecimal feeamt = Decimals.div(Decimals.mul(relFeecurAmt, request.getPerrattr3()), basis);
                    feeamt = xrtmodService.amtRnd(feeamt, feecur);
                    feeamt = Decimals.mul(feeamt, tirunt);
                    fecamt1 = Decimals.add(fecamt1, feeamt);
                    inftxt += CR + Strings.getText("从第$1段开始使用费率$2,单元为$3,计算费用金额为$4",request.getPerbegtr3(), request.getPerrattr3(), tirunt, feeamt);
                    lftunt = Decimals.sub(lftunt, tirunt);
                }
                if (MdaUtils.compareTo(Decimals.add(lftunt, oldper), request.getPerbegtr2()) >= 0 && request.getPerbegtr2() != 0) {
                    tirunt = Decimals.add(Decimals.sub(Decimals.add(lftunt, oldper), request.getPerbegtr2()), 1);
                    tirunt = getMinimum(tirunt, lftunt);
                    BigDecimal feeamt = Decimals.div(Decimals.mul(relFeecurAmt, request.getPerrattr2()), basis);
                    feeamt = xrtmodService.amtRnd(feeamt, feecur);
                    feeamt = Decimals.mul(feeamt, tirunt);
                    fecamt1 = Decimals.add(fecamt1, feeamt);
                    inftxt += CR + Strings.getText("从第$1段开始使用费率$2,单元为$3,计算费用金额为$4",request.getPerbegtr2(), request.getPerrattr2(), tirunt, feeamt);
                    lftunt = Decimals.sub(lftunt, tirunt);
                    if (lftunt.compareTo(BigDecimal.ZERO) > 0) {
                        feeamt = Decimals.div(Decimals.mul(relFeecurAmt, ratuse), basis);
                        feeamt = xrtmodService.amtRnd(feeamt, feecur);
                        feeamt = Decimals.mul(feeamt, lftunt);
                        inftxt += CR + Strings.getText("从第1段开始使用费率$1,单元为$2,计算费用金额为$3",ratuse, lftunt, feeamt);
                    }
                }
                BigDecimal feeamt = Decimals.div(Decimals.mul(relFeecurAmt, ratuse), basis);
                feeamt = xrtmodService.amtRnd(feeamt, feecur);
                Argument<String> roundInftxtArg = new Argument<>("", "");
                feeamt = roundAmt(roundInftxtArg, feeamt, request.getRoundFlag());
                if (StringUtils.isNotEmpty(roundInftxtArg.value)) {
                    inftxt += CR + roundInftxtArg.value;
                }
                feeamt = Decimals.mul(feeamt, lftunt);
                fecamt1 = Decimals.add(fecamt1, feeamt);
                inftxt += CR + Strings.getText("计算后应收 $1 $2", feecur, Utils.fmtAmount(fecamt1, feecur));
            }
            //展期部分计算费用
            int addpernum = perprv - oldperprv;
            if (addpernum > 0) {
                inftxt += CR + Strings.getText("开始计算展期基于余额 $1 $2 费用", feecur, Utils.fmtAmount(opnamt, feecur));
                fecamt2 = new BigDecimal("0");
                BigDecimal lftunt = new BigDecimal(perprv);
                BigDecimal tirunt = null;
                if (MdaUtils.compareTo(lftunt, request.getPerbegtr5()) >= 0 && request.getPerbegtr5() != 0) {
                    tirunt = Decimals.add(Decimals.sub(lftunt, request.getPerbegtr5()), 1);
                    tirunt = getMinimum(tirunt, Decimals.sub(lftunt, oldperprv));
                    BigDecimal feeamt = Decimals.div(Decimals.mul(opnamt, request.getPerrattr5()), basis);
                    feeamt = xrtmodService.amtRnd(feeamt, feecur);
                    feeamt = Decimals.mul(feeamt, tirunt);
                    fecamt2 = Decimals.add(fecamt2, feeamt);
                    inftxt += CR + Strings.getText("从第$1段开始使用费率$2,单元为$3,计算费用金额为$4",request.getPerbegtr5(), request.getPerrattr5(), tirunt, feeamt);
                    lftunt = Decimals.sub(lftunt, tirunt);
                }
                if (MdaUtils.compareTo(lftunt, request.getPerbegtr4()) >= 0 && request.getPerbegtr4() != 0 && MdaUtils.compareTo(lftunt, oldperprv) > 0) {
                    tirunt = Decimals.add(Decimals.sub(lftunt, request.getPerbegtr4()), 1);
                    tirunt = getMinimum(tirunt, Decimals.sub(lftunt, oldperprv));
                    BigDecimal feeamt = Decimals.div(Decimals.mul(opnamt, request.getPerrattr4()), basis);
                    feeamt = xrtmodService.amtRnd(feeamt, feecur);
                    feeamt = Decimals.mul(feeamt, tirunt);
                    fecamt2 = Decimals.add(fecamt2, feeamt);
                    inftxt += CR + Strings.getText("从第$1段开始使用费率$2,单元为$3,计算费用金额为$4",request.getPerbegtr4(), request.getPerrattr4(), tirunt, feeamt);
                    lftunt = Decimals.sub(lftunt, tirunt);
                }
                if (MdaUtils.compareTo(lftunt, request.getPerbegtr3()) >= 0 && request.getPerbegtr3() != 0 && MdaUtils.compareTo(lftunt, oldperprv) > 0) {
                    tirunt = Decimals.add(Decimals.sub(lftunt, request.getPerbegtr3()), 1);
                    tirunt = getMinimum(tirunt, Decimals.sub(lftunt, oldperprv));
                    BigDecimal feeamt = Decimals.div(Decimals.mul(opnamt, request.getPerrattr3()), basis);
                    feeamt = xrtmodService.amtRnd(feeamt, feecur);
                    feeamt = Decimals.mul(feeamt, tirunt);
                    fecamt2 = Decimals.add(fecamt2, feeamt);
                    inftxt += CR + Strings.getText("从第$1段开始使用费率$2,单元为$3,计算费用金额为$4",request.getPerbegtr3(), request.getPerrattr3(), tirunt, feeamt);
                    lftunt = Decimals.sub(lftunt, tirunt);
                }
                if (MdaUtils.compareTo(lftunt, request.getPerbegtr2()) >= 0 && request.getPerbegtr2() != 0 && MdaUtils.compareTo(lftunt, oldperprv) > 0) {
                    tirunt = Decimals.add(Decimals.sub(lftunt, request.getPerbegtr2()), 1);
                    tirunt = getMinimum(tirunt, Decimals.sub(lftunt, oldperprv));
                    BigDecimal feeamt = Decimals.div(Decimals.mul(opnamt, request.getPerrattr2()), basis);
                    feeamt = xrtmodService.amtRnd(feeamt, feecur);
                    feeamt = Decimals.mul(feeamt, tirunt);
                    fecamt2 = Decimals.add(fecamt2, feeamt);
                    inftxt += CR + Strings.getText("从第$1段开始使用费率$2,单元为$3,计算费用金额为$4",request.getPerbegtr2(), request.getPerrattr2(), tirunt, feeamt);
                    lftunt = Decimals.sub(lftunt, tirunt);
                }
                if (MdaUtils.compareTo(lftunt, oldperprv) > 0) {
                    BigDecimal feeamt = Decimals.div(Decimals.mul(opnamt, ratuse), basis);
                    feeamt = xrtmodService.amtRnd(feeamt, feecur);
                    feeamt = Decimals.mul(feeamt, Decimals.sub(lftunt, oldperprv));
                    fecamt2 = Decimals.add(fecamt2, feeamt);
                    inftxt += CR + Strings.getText("从第1段开始使用费率$1,单元为$2,计算费用金额为$3", ratuse, Decimals.sub(lftunt, oldperprv), feeamt);
                }
                Argument<String> roundInftxtArg = new Argument<>("", "");
                fecamt2 = roundAmt(roundInftxtArg, fecamt2, request.getRoundFlag());
                if (StringUtils.isNotEmpty(roundInftxtArg.value)) {
                    inftxt += CR + roundInftxtArg.value;
                }
                inftxt += CR + Strings.getText("计算后应收 $1 $2", feecur, Utils.fmtAmount(fecamt2, feecur));
            }
            BigDecimal fecamt = Decimals.add(fecamt1, fecamt2);
            inftxt += CR + Strings.getText("总费用金额为 $1 $2", feecur, Utils.fmtAmount(fecamt, feecur));
            ogiamt = xrtmodService.amtRndUnt(fecamt, feecur);
            amt = xrtmodService.amtRndUnt(Decimals.sub(fecamt, request.getDctamt()), feecur);
        }
        response.setUnt(unt);
        response.setInftxt(inftxt);
        response.setOgiamt(ogiamt);
        response.setCur(feecur);
        response.setAmt(amt);
        response.setDat1(date1);
        response.setDat2(date2);
        compareMaxmin(response, request);
        return response;
    }
}
