package com.brilliance.isc.common.register.fee.common;


import cn.hutool.core.lang.Assert;
import com.brilliance.isc.common.context.SettleContext;
import com.brilliance.isc.common.liaall.service.LiaallService;
import com.brilliance.isc.common.liaall.vo.LiaallVo;
import com.brilliance.isc.common.liaallg.service.LiaallgService;
import com.brilliance.isc.common.liaallg.vo.LiaallgVo;
import com.brilliance.isc.common.register.fee.IFeeRegister;
import com.brilliance.isc.common.setfeg.service.SetfegService;
import com.brilliance.isc.common.setmod.service.SetmodService;
import com.brilliance.isc.common.setmod.vo.SetmodVo;
import com.brilliance.isc.common.util.Utils;
import com.brilliance.isc.common.vo.SimpleModuleVo;
import com.brilliance.mda.runtime.mda.impl.Argument;
import com.brilliance.mda.runtime.mda.util.Dates;
import com.brilliance.mda.runtime.mda.util.MdaUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

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

import static com.brilliance.mda.runtime.mda.Constants.*;

@Component("liaall.feeRegister")
public class LiaallFeeRegister implements IFeeRegister {

    private static Logger log = LoggerFactory.getLogger(LiaallFeeRegister.class);

    @Autowired
    private LiaallService liaallService;

    @Autowired
    private LiaallgService liaallgService;

    @Autowired
    private SetfegService setfegService;

    @Autowired
    private SetmodService setmodService;

    @Override
    public void registerSettlement(SetmodVo setmod) {
        // remove old fee definitions if any
        // use registersettlement in transction or registersettlementLiaXX in SETxxD-Modules to superordinate
        setfegService.remTrnFeeGroup("TRNLIA");
        setfegService.remTrnFeeGroup("TRNLII");
        LiaallVo liaall = setmod.getLiaall();
        if(liaall == null) return;
        List<LiaallgVo> liaallgs = liaall.getLiaallg();
        // define fees for LIAALL
        int gridcnt = 0;
        if (liaallgs != null) {
            gridcnt = liaallgs.size();
        }
        String sw = NULLSTR;
        int un = 0;
        Date begdat = null;
        Date todat = null;
        String roldbt = NULLSTR;
        String wrn = NULLSTR;
        String rolRpl = NULLSTR;
        Date expdat = null;
        String tilmat = NULLSTR;
        String inccod = NULLSTR;
        String irtinc = NULLSTR;
        for (int i = 0; i < gridcnt; i++) {
            Assert.notNull(liaallgs);
            LiaallgVo liaallg = liaallgs.get(i);
            sw = "N";
            un = 0;
            begdat = liaallg.getPtegrp().getRec().getBegdat();
            todat = liaallg.getSetdatold();
            roldbt = liaallg.getPtegrp().getRec().getRolpay();
            wrn = "";
            rolRpl = liaallService.liaallParGet("ROLRPL", roldbt);
            if (!MdaUtils.isEmpty(rolRpl)) {
                roldbt = rolRpl;
            }
            while (true) {
                if ((!MdaUtils.isEmpty(liaallg.getRol())) && (!MdaUtils.isEmpty(liaallg.getFeecod())) && MdaUtils.isEmpty(liaallg.getFeehndidx())) {
                    expdat = liaallg.getFeecodExpdat();
                    if (expdat == NULLDATE) {
                        // In GI take +5000 to support unlimited guarantees. Otherwise no defaulting if date not set by transaction
                        if (MdaUtils.compareTo(SettleContext.getUserSession().getAtp().getBus(), "GI") == 0
                            || MdaUtils.compareTo(SettleContext.getUserSession().getAtp().getBus(), "NI") == 0) {
                            expdat = Dates.add(setmod.getRefdat(), 5000);
                        } else {
                            expdat = Utils.getMinDate();
                        }
                    }
                    // if to be settled till maturity, set end dat to maturity dat if already set
                    tilmat = liaallg.getTilmat();
                    if (!MdaUtils.isEmpty(tilmat)) {
                        if (!MdaUtils.isEmpty(liaallg.getMatdat())) {
                            expdat = liaallg.getMatdat();
                        }
                    }
                    // if no settlement before or recaclulation requiered from condition, start commission caclulation from start date
                    if (MdaUtils.isEmpty(liaallg.getSetdatold()) || !MdaUtils.isEmpty(liaallg.getFec().getClcdifflg())) {
                        begdat = liaallg.getPtegrp().getRec().getBegdat();
                        // special handling if SETDATOLD has already been set
                        if (!MdaUtils.isEmpty(liaallg.getSetdatold())) {
                            // If new period starts, calculate that period
                            if (Dates.diff(liaallg.getSetdatold(), setmod.getRefdat()) <= 0) {
                                begdat = Dates.add(liaallg.getSetdatold(), 1);
                            } else {
                                Argument<Date> begdatBox = new Argument<Date>("", begdat);
                                Argument<Date> todatBox = new Argument<Date>("", todat);
                                Argument<String> wrnBox = new Argument<String>("", wrn);
                                liaallService.getRelevantDates(liaall, i, begdatBox, todatBox, wrnBox);

                                begdat = begdatBox.value;
                                todat = todatBox.value;
                                wrn = wrnBox.value;

                                if (!MdaUtils.isEmpty(wrn)) {
                                    break; //   ####   goto SetFee
                                }
                            }
                        }
                        todat = expdat;
                    } else {
                        // as standard implementation used closed intervall, 1 day has to be added if there is an old date.
                        // has to match with calculation logic in FECISM/IRTCAL
                        begdat = Dates.add(liaallg.getSetdatold(), 1);
                        if (Dates.diff(begdat, setmod.getRefdat()) > 0) {
                            todat = NULLDATE;
                        } else {
                            todat = expdat;
                        }
                    }
                    // DO5DOS.004971 - do not default fee as long as to date not set (may lead to loops in calculation depending on calculation method)
                    if (!MdaUtils.isEmpty(begdat) && MdaUtils.isEmpty(todat)) {
                        todat = Utils.getMinDate();
                    }
                    if (Dates.diff(begdat, setmod.getRefdat()) <= 0 && Dates.diff(begdat, todat) <= 0) {
                        sw = "Y";
                        un = 0;
                    }
                }
                break;
            }
            //    ####    label SetFee
            if (MdaUtils.compareTo(liaallg.getFec().getSettyp(), "E") == 0 && MdaUtils.isEmpty(liaallg.getSetdatold())) {
                todat = NULLDATE;
            }
            log.warn("LIAALLFEEWRN" + MdaUtils.toString(i + 1, -2) + " " + wrn);
            setfegService.addTrnFee("TRNLIA" + MdaUtils.toString(i + 1, -2), liaallg.getFee().getCod(), sw, un, begdat, todat, BigDecimal.ZERO, BigDecimal.ZERO, "", "OBJMOD=" + liaallgService.getObjMod(i) + CR + "FECMOD=//LIAALL//LIAALLG(" + i + ")//FEC" + CR + "ROLDBT=" + roldbt + CR + "CBTPFX=" + liaallg.getCbtpfx() + CR + "CEXTID=" + liaallg.getExtid());
            inccod = liaallg.getFeeinccod();
            sw = "N";
            un = 0;
            begdat = liaallg.getValdat();
            if (MdaUtils.isEmpty(begdat)) {
                begdat = Dates.today();
            }
            todat = liaallg.getSetdatold();
            // create seperate increase fee for increase, extension and only if no recalculation is done for main comission
            if (!MdaUtils.isEmpty(inccod) && MdaUtils.compareTo(liaallg.getAmt(), 0) > 0 && Dates.diff(todat, begdat) >= 0 && MdaUtils.isEmpty(liaallg.getFec().getClcdifflg())) {
                sw = "Y";
            }
            if (MdaUtils.isEmpty(liaallg.getFec().getRatirsinc())) {
                irtinc = liaallg.getFec().getRatirs();
            } else {
                irtinc = liaallg.getFec().getRatirsinc();
            }
            setfegService.addTrnFee("TRNLII" + MdaUtils.toString(i, -2), inccod, sw, un, begdat, todat, liaallg.getFec().getRatcal(), liaallg.getAmt(), "", "OBJMOD=" + liaallgService.getObjMod(i) + CR + "NOFECMOD=//LIAALL//LIAALLG(" + i + ")//FEC" + CR + "FECIRT=" + irtinc + CR + "ROLDBT=" + roldbt + CR + "CBTPFX=" + liaallg.getCbtpfx() + CR + "CEXTID=" + liaallg.getExtid());
        }
        setfegService.setfegClrCbsAmt("LIAALL");
        for (int liaidx = 0; liaidx < gridcnt; liaidx++) {
            Assert.notNull(liaallgs);
            LiaallgVo liaallg = liaallgs.get(liaidx);
            if (MdaUtils.compareTo(liaallg.getAmt(), 0) != 0 && (!MdaUtils.isEmpty(liaallg.getCur()))) {
                SimpleModuleVo linkModule = SimpleModuleVo.buildModule(liaallg.getPtegrp().getRec().getInr(), "PTE");
               setfegService.setfegAddCbsAmt("LIAALL", liaallg.getRol(), liaallg.getCur(), liaallg.getAmt(), "AMT1", "LIASUM", Utils.toJson(linkModule), liaallg.getValdat());
            }
        }
        setmod.setMatdat(liaall.getTensetmatdat());
    }

}
