package com.brilliance.isc.common.setfog.service.impl;


import com.brilliance.mda.runtime.mda.CodetableItem;
import com.brilliance.mda.runtime.mda.IStream;
import com.brilliance.mda.runtime.mda.impl.StreamImpl;
import com.brilliance.mda.runtime.mda.util.*;
import com.brilliance.isc.common.cbsmod.service.XrtmodService;
import com.brilliance.isc.common.codetable.service.CodetableService;
import com.brilliance.isc.common.contants.CommonContants;
import com.brilliance.isc.common.context.SettleContext;
import com.brilliance.isc.common.setfog.service.SetfolService;
import com.brilliance.isc.common.setfog.vo.SetfolVo;
import com.brilliance.isc.common.setglg.service.SetglgService;
import com.brilliance.isc.common.setmod.vo.SetmodVo;
import com.brilliance.isc.common.util.StringUtils;
import com.brilliance.isc.common.util.Utils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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

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

@Service
public class SetfolServiceImpl implements SetfolService {

    @Autowired
    private SetglgService setglgService;

    @Autowired
    private XrtmodService xrtmodService;

    @Autowired
    private CodetableService codetableService;

    /**
     * source:setfol.0005.script
     */
    @Override
    public String ruleDetpN1000(SetmodVo setmod) {
        String clcamtlab = Strings.getText("Calculate amount from $1 $2 $3",
                CommonContants.DOC_AMT_TYP_CODES.get(setmod.getDocamttyp()),
                setmod.getDoccur(),
                Utils.fmtAmount(setmod.getDocamt(), setmod.getDoccur()));
        return clcamtlab;
    }

    /**
     * source:setfol.0006.script
     */
    @Override
    public String calcMac(SetfolVo setfol, SetmodVo setmod) {
        // Start with installation specific portion
        IStream stm = new StreamImpl();
        Streams.streamSet(stm, setmod.getSetfog().getDsppoldft());
        Streams.streamInsert(stm, 0, setmod.getRoldsc());
        //Streams.streamInsert(stm,0, setmod.getDspflg());
        // calculate mac : DSP + PTYDBT + PTYPAY + CUR + AMT + DAT1 + DAT2 + RAT
        Streams.streamInsert(stm, 0, setfol.getDsp() + setfol.getPtydbt()
                + setfol.getPtypay() + setfol.getCur()
                + Numerics.round(setfol.getAmt(), 2)
                + Utils.fmtDate(setfol.getDat1())
                + Utils.fmtDate(setfol.getDat2())
                + Numerics.round(setfol.getRat(), 6));
        // as dspcalc depends on amount settled
        if (!StringUtils.isEmpty(setfol.getPtydbt()) && !StringUtils.isEmpty(setfol.getPtypay())) {
            Streams.streamInsert(stm, 0, MdaUtils.toString(Numerics.round(setglgService.getSetAmtSysByRolTypDsp(setmod.getSetglg(), setfol.getPtydbt(), "", ""), 2)));
            Streams.streamInsert(stm, 0, MdaUtils.toString(Numerics.round(setglgService.getSetAmtSysByRolTypDsp(setmod.getSetglg(), setfol.getPtypay(), "", ""), 2)));
        }
        String mac = Systems.macGen(stm, 0);
        setfol.setMac(mac);
        return mac;
    }

    /**
     * source:setfol.0002.script
     */
    @Override
    public void recalcSetfol(SetfolVo setfol, SetmodVo setmod) {
        recalcSetfolStdDft(setfol, setmod);
        String mac = calcMac(setfol, setmod);
        setfol.setMac(mac);
        setfol.setMacold(mac);
    }

    /**
     * source:setfol.0007.script
     */
    public void dspCalc(SetfolVo setfol, SetmodVo setmod) {
        if (setfol.getAmt().compareTo(BigDecimal.ZERO) == 0) {
            setfol.setDsp("");
        } else {
            String setDef = "X";
            String poolDef = "";
             /*if ("C".equals(setmod.getDspflg())) {
                 setDef = "S";
             } else {
                 setDef = "X";
             }*/
            boolean trnsetflg = false;
            if ("*".equals(setmod.getSetfeg().getRoldspmdyflg()) || setfol.getPtydbt().equals(setmod.getSetfeg().getRoldspmdyflg())) {
                trnsetflg = true;
            }
            if (trnsetflg) {
                setfol.setDsp(setDef);
                return;
            }
            if (setfol.isModified("dsp")) return;
            if ("D".equals(setfol.getSrc()) || "A".equals(setfol.getSrc())) {
                poolDef = "D";
            } else {
                poolDef = setmod.getSetfog().getDsppoldft();
            }
             /*if (!StringUtils.isEmpty(setmod.getSep().getInr())) {
                 if ("A".equals(setfol.getSrc())) {
                     setDef = "X";
                     poolDef = "X";
                 }
             }*/
            // retrieve valid default option (if set by SetmodSetRolFeeDspDefault, take it, if not take CLISETOPT/FORSETOPT)
            String validOpt = "";
            int paridx = Streams.streamSearch(setmod.getParstm(),"ROL-" + setfol.getPtydbt() + "-FEEDSP-" + TAB);
            if( paridx > 0 ) {
                String parlin = Strings.getLine(setmod.getParstm(),paridx);
                validOpt = Strings.mid(parlin,Strings.pos(parlin,TAB) + 1);
            } else {
                if (MdaUtils.compareTo(Strings.mid(setfol.getPtydbt(), 1, 2), Strings.mid(setmod.getFeeclirol(), 1, 2)) == 0) {
                    validOpt = setmod.getClisetopt();
                } else {
                    validOpt = setmod.getForsetopt();
                }
            }
            if ("U".equals(validOpt) && ("D".equals(setfol.getSrc()) || "P".equals(setfol.getSrc()))) {
                setfol.setDsp(setfol.getSrc());
            } else {
                switch (validOpt) {
                    case "P":
                    case "V":
                        setfol.setDsp(poolDef);
                        break;
                    case "S":
                    case "X":
                        setfol.setDsp(setDef);
                        break;
                    default:
                        // if no option is set, default is settle to clients...
                        if (MdaUtils.compareTo(Strings.mid(setfol.getPtydbt(), 1, 2), Strings.mid(setmod.getFeeclirol(), 1, 2)) == 0) {
                            setfol.setDsp(setDef);
                        } else {
                            // ... and setlle to foreign parties only if there are getting in settlement anyway
                            // if role is in settlement amounts, default to settle now
                            if (setglgService.getSetAmtSysByRolTypDsp(setmod.getSetglg(), setfol.getPtydbt(), "", "").compareTo(BigDecimal.ZERO) != 0) {
                                setfol.setDsp(setDef);
                            } else {
                                setfol.setDsp(poolDef);
                            }
                        }
                }
            }
        }
    }

    /**
     * source:setfol.0008.script
     */
    public void recalcSetfolStdDft(SetfolVo setfol, SetmodVo setmod) {
        // disable if fee has already been advised
        if ("f".equals(setfol.getModflg()) || "D".equals(setfol.getSrc()) || "F".equals(setfol.getSrc())) {

        } else {
            if (!StringUtils.isEmpty(setfol.getPtypay()) && !StringUtils.isEmpty(setfol.getPtydbt())
                    && !setfol.isModified("amt")) {
                if (setfol.getRat().compareTo(BigDecimal.ZERO) != 0
                        && setfol.getDat1() != null
                        && setfol.getDat2() != null) {
                    /**
                     //--光大的需求，所有的都按照360计算，--wcx
                     $clcamt = DOCAMT * RAT * DateDiff( DAT2, DAT1 ) / 36500
                     **/
                    BigDecimal clcamt = Decimals.div(Decimals.mul(Decimals.mul(setmod.getDocamt(), setfol.getRat()), Dates.diff(setfol.getDat2(), setfol.getDat1())), 36000);
                    setfol.setAmt(xrtmodService.amtRnd(clcamt, setfol.getCur()));
                }
            }
        }
        // from default DAT2
        if (setfol.getRat().compareTo(BigDecimal.ZERO) != 0 && setfol.getDat1() != null && setfol.getDat2() == null) {
            setfol.setDat2(Dates.add(Dates.today(), -1));
        }
        // Default SRCFLG
        if (MdaUtils.isEmpty(setfol.getSrcfcpinr())) {
            if (setfol.getAmt().compareTo(BigDecimal.ZERO) == 0) {
                setfol.setSrc("");
            } else {
                if (StringUtils.isEmpty(setfol.getSrc())) {
                    setfol.setSrc("U");
                }
            }
        } else {
            if (StringUtils.isEmpty(setfol.getAdvtrninr())) {
                setfol.setSrc("P");
            } else {
                if (MdaUtils.isEmpty(setfol.getSepinr())) {
                    setfol.setSrc("D");
                } else {
                    setfol.setSrc("A");
                }
            }
        }
        // from default CUR only if source is not pool
        //如果payer或者payeer不为空，才给CUR赋值
        if (!StringUtils.isEmpty(setfol.getPtydbt()) || !StringUtils.isEmpty(setfol.getPtypay())) {
            if (!"P".equals(setfol.getSrc()) && !"A".equals(setfol.getSrc()) && !"D".equals(setfol.getSrc())) {
                if (StringUtils.isEmpty(setfol.getCur()) || !setfol.isModified("cur")) {
                    setfol.setCur(setmod.getDoccur());
                }
            }
        }
        dspCalc(setfol, setmod);
        IStream rolstm = new StreamImpl();
        Streams.streamSet(rolstm, setmod.getRoldsc());
        int ptypaylin = Streams.streamSearch(rolstm, setfol.getPtypay() + TAB);
        if (ptypaylin > 0) {
            Streams.streamDelete(rolstm, ptypaylin);
        }
        //刘文青的需求，到单和付款交易中，foreogn payer不需要光大银行选项。
        //String trnNam = SettleContext.getTransName();
        String trnNam = SettleContext.getDirectTransName();
        int ptypaylinZZ = 0;
        if ("LITDCK".equals(trnNam) || "BRTSET".equals(trnNam)) {
            ptypaylinZZ = Streams.streamSearch(rolstm, "OWN" + TAB);
            if (ptypaylinZZ > 0) {
                Streams.streamDelete(rolstm, ptypaylinZZ);
            }
        }
        //收汇交易，信用证下默认一条ben给issuing bank，转让证下be1给trans. bank，托收下ben给col.bank
        //betset注册类中已经实现
        /*if ("BETSET".equals(trnNam)) {
            if (Streams.streamSearch(rolstm, "BEN" + TAB) > 0 && !setfol.isModified("ptydbt")) {
                setfol.setPtydbt("BEN");
            }
            if (Streams.streamSearch(rolstm, "ISS" + TAB) > 0 && !setfol.isModified("ptypay")) {
                setfol.setPtypay("ISS");
            }
        }*/
        //botset注册类中已经实现
        /*if ("BOTSET".equals(trnNam)) {
            if (Streams.streamSearch(rolstm, "DRR" + TAB) > 0 && !setfol.isModified("ptydbt")) {
                setfol.setPtydbt("DRR");
            }
            if (Streams.streamSearch(rolstm, "COL" + TAB) > 0 && !setfol.isModified("ptypay")) {
                setfol.setPtypay("COL");
            }
        }*/
        if ("BTTSET".equals(trnNam)) {
            if (Streams.streamSearch(rolstm, "BE1" + TAB) > 0 && !setfol.isModified("ptydbt")) {
                setfol.setPtydbt("BE1");
            }
            if (Streams.streamSearch(rolstm, "ADT" + TAB) > 0 && !setfol.isModified("ptypay")) {
                setfol.setPtypay("ADT");
            }
        }
        //payer payee下拉列表
        setfol.setPayerSet(buildCodetable(rolstm));
        Streams.streamSet(rolstm, setmod.getRoldsc());
        int ptydbtlin = Streams.streamSearch(rolstm,setfol.getPtydbt() + TAB);
        if( ptydbtlin > 0 ) {
            Streams.streamDelete(rolstm,ptydbtlin);
        }
        setfol.setPayeeSet(buildCodetable(rolstm));
        setfol.setTxtdbt(setFolGetTxtdbt(setfol));
        setfol.setTxtpay(setFolGetTxtpay(setfol));
    }

    /**
     * source:setfol.0009.script
     */
    public String setFolGetTxtdbt(SetfolVo setfol) {
        if ("AGT".equals(setfol.getPtypay())) {
            return CommonContants.TXT_STD_CODES.get("ACM");
        } else {
            return CommonContants.TXT_STD_CODES.get("FCH");
        }
    }

    /**
     * source:setfol.0010.script
     */
    public String setFolGetTxtpay(SetfolVo setfol) {
        if ("AGT".equals(setfol.getPtypay())) {
            return CommonContants.TXT_STD_CODES.get("COM");
        } else {
            return CommonContants.TXT_STD_CODES.get("YCH");
        }
    }

    /**
     * source:setfol.0010.script
     */
    public String setFolGetTxtpay(SetfolVo setfolVo, String argUil) {
        //! (re)set text for TXTPAY according to actual role
        String res;
        if (MdaUtils.isEmpty(setfolVo.getPtypay())) {
            res = "";
        } else {
            res = setfolVo.getTxtpay();
            //  if not IsModified( TxtPay ) then
            if (MdaUtils.isEmpty(setfolVo.getTxtpay())) {
                if ("AGT".equals(setfolVo.getPtypay())) {
                    res = codetableService.getTblLabel("COM", "SETFOL:TXTSTD", argUil);
                } else {
                    res = codetableService.getTblLabel("YCH", "SETFOL:TXTSTD", argUil);
                }
            }
        }
        return res;
    }

    /**
     * source:setfol.0009.script
     */
    public String setFolGetTxtdbt(SetfolVo setfolVo, String argUil) {
        //! (re)set text for TXTDBT according to actual role
        String res;
        if (MdaUtils.isEmpty(setfolVo.getPtypay())) {
            res = "";
        } else {
            res = setfolVo.getTxtdbt();
            //  if not IsModified( TXTDBT ) then
            if (MdaUtils.isEmpty(setfolVo.getTxtdbt())) {
                if ("AGT".equals(setfolVo.getPtypay())) {
                    res = Codetables.getCodetableLabelOfTd("ACM", "SETFOL:TXTSTD", argUil);
                } else {
                    res = Codetables.getCodetableLabelOfTd("FCH", "SETFOL:TXTSTD", argUil);
                }
            }
        }
        return res;

    }

    private List<CodetableItem> buildCodetable(IStream rolstm) {
        List<CodetableItem> codetableItems = new ArrayList<>();
        for (int i = 1; i <= Streams.streamCount(rolstm); i++) {
            String line = rolstm.getLine(i);
            String[] lines = line.split(TAB);
            if (lines != null && lines.length == 2) {
                codetableItems.add(new CodetableItem(lines[1], lines[0]));
            }
        }
        return codetableItems;
    }
}
