package com.brilliance.isc.swift.fremsg.check;

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 com.brilliance.mda.runtime.mda.util.Strings;
import com.brilliance.isc.common.context.SettleContext;
import com.brilliance.isc.common.transaction.newcheck.*;
import com.brilliance.isc.common.transaction.vo.BaseTransactionVo;
import com.brilliance.isc.common.trndoc.vo.DoceotVo;
import com.brilliance.isc.common.trnmod.service.TrnmodService;
import com.brilliance.isc.common.util.StringUtils;
import com.brilliance.isc.common.vo.FremsgVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

@Component
public class FremsgValidator extends AbstractModuleValidator<FremsgVo> {
    @Autowired
    private TrnmodService trnmodService;

    @Override
    @PostConstruct
    public void register() {
        super.register();
    }

    /**
     * source:fremsg.0008.script
     */
    @Validate(path = "fremsg.ccrol")
    public ValidResult checkCcrolN1000(FremsgVo fremsgVo) {
        if ((!MdaUtils.isEmpty(fremsgVo.getCcrol())) && MdaUtils.compareTo(fremsgVo.getCcrol(), "OTH") != 0) {
            if (MdaUtils.compareTo(fremsgVo.getCcrol(), fremsgVo.getMsgrol()) == 0) {
                return ValidResult.build(false, getI18NString("fremsg", "CT000000"));
            }
        }
        return null;
    }

    /**
     * source:fremsg.0016.script
     */
    @Validate(path = "fremsg.relmt")
    public ValidResult checkRelmtN1000(FremsgVo fremsgVo) {
        //mandatory check for message types Request of cancellation, query or answer
        if ((MdaUtils.compareTo(fremsgVo.getSndmt(), "92") == 0 || MdaUtils.compareTo(fremsgVo.getSndmt(), "95") == 0 || MdaUtils.compareTo(fremsgVo.getSndmt(), "96") == 0) && MdaUtils.isEmpty(fremsgVo.getRelmt())) {
            return errorMandatory();
        }
        return null;
    }

    /**
     * source:fremsg.0018.script
     */
    @Validate(path = "fremsg.det")
    public ValidResult checkDetN1000(FremsgVo fremsgVo) {
        if ((MdaUtils.compareTo(fremsgVo.getSndmt(), "95") == 0 || MdaUtils.compareTo(fremsgVo.getSndmt(), "96") == 0) && MdaUtils.isEmpty(fremsgVo.getDet())) {
            return errorMandatory();
        }
        return null;
    }

    /**
     * source:fremsg.0021.script
     */
    @Validate(path = "fremsg.tag45d")
    public ValidResult checkTag45dN1000(FremsgVo fremsgVo) {
        // DNGDEV.000354
        if (MdaUtils.compareTo(fremsgVo.getSndmt(), "59") == 0) {
            if (MdaUtils.isEmpty(fremsgVo.getTag45d())) {
                return errorMandatory();
            }
        }
        return null;
    }

    /**
     * source:fremsg.0041.script
     */
    @Validate(path = "fremsg.tag22d")
    public ValidResult checkTag22dN1000(FremsgVo fremsgVo) {
        // DNGDEV.000354
        boolean flgTag22DMandatory = false;
        int numMsgCnt = 0;
        if (MdaUtils.compareTo(fremsgVo.getSndmt(), "59") == 0) {
            if (MdaUtils.isEmpty(fremsgVo.getTag22d())) {
                // DNGDEV.002160 - Tag 22D is not mandatory for G06
                flgTag22DMandatory = true;
                // dngdev.002636 - remove sr2019 active restriction
                BaseTransactionVo parent = (BaseTransactionVo) getParent();
                for (DoceotVo doceotVo : parent.getDoceot()) {
                    if (doceotVo.getRole().equals(fremsgVo.getMsgrol())) {
                        if (doceotVo.getCortyp().equals("DTG")) {
                            flgTag22DMandatory = false;
                            break;
                        }
                    }
                }
                if (flgTag22DMandatory) {
                    return errorMandatory();
                }
            }
        }
        // DNGDEV.001013 - please check that default MT741P and checks for fields aon panel are consistent
        //DNGDEV.001562 - Also for GI/GC
        String bus = SettleContext.getUserSession().getAtp().getBus();
        if (MdaUtils.compareTo(fremsgVo.getSndmt(), "92") == 0 && MdaUtils.compareTo(fremsgVo.getAdrbicaut(), "S") == 0 && MdaUtils.isEmpty(fremsgVo.getTag22d()) && (MdaUtils.compareTo(bus, "LI") == 0 || MdaUtils.compareTo(bus, "LE") == 0 || MdaUtils.compareTo(bus, "GI") == 0 || MdaUtils.compareTo(bus, "GC") == 0)) {
            return errorMandatory();
        }
        return null;
    }

    /**
     * source:fremsg.0042.script
     */
    @Validate(path = "fremsg.tag23h")
    public ValidResult checkTag23hN1000(FremsgVo fremsgVo) {
        // DNGDEV.000354
        boolean v23hOK = false;
        int doceotcnt = 0;
        String cortyp = "";
        String msgrol = "";
        String ccrol = "";
        if (MdaUtils.compareTo(fremsgVo.getSndmt(), "59") == 0) {
            if (MdaUtils.isEmpty(fremsgVo.getTag23h())) {
                return errorMandatory();
                // execution of check only, if tag is visible  (i.e. SNDMT is "59")
            } else {
                //DNGDEV.1001 check allowed code regarding selected cortyp of Msg
                BaseTransactionVo parent = (BaseTransactionVo) getParent();
                cortyp = "";
                for (DoceotVo doceotVo : parent.getDoceot()) {
                    //dngdev.001356
                    msgrol = fremsgVo.getMsgrol();
                    if (MdaUtils.compareTo(msgrol, "FRE") == 0) {
                        msgrol = "FMO";
                    }
                    ccrol = fremsgVo.getCcrol();
                    if (MdaUtils.compareTo(ccrol, "FRE") == 0) {
                        ccrol = "FMC";
                    }
                    if ((MdaUtils.compareTo(doceotVo.getRole(), msgrol) == 0 && MdaUtils.compareTo(doceotVo.getId(), "TRNFRE1") == 0) || (MdaUtils.compareTo(doceotVo.getRole(), ccrol) == 0 && MdaUtils.compareTo(doceotVo.getId(), "TRNFRE2") == 0)) {
                        cortyp = doceotVo.getCortyp();
                        // all codes allowed with letter, email
                        if (MdaUtils.compareTo(cortyp, "LET") == 0 || MdaUtils.compareTo(cortyp, "EML") == 0) {
                            v23hOK = true;
                        } else {
                            // codes allowed only for specific cortypes
                            switch (fremsgVo.getTag23h()) {
                                //DO5DZB.004023 function must be allowed for TCO if itis allowed for DTA/DTE
                                case "GENINFAD":
                                case "OTHERFNC":
                                    // DO5HTR.001653
                                    if (MdaUtils.compareTo(cortyp, "DTA") == 0 || MdaUtils.compareTo(cortyp, "DTE") == 0 || MdaUtils.compareTo(cortyp, "TCO") == 0 || MdaUtils.compareTo(cortyp, "SWT") == 0 || MdaUtils.compareTo(cortyp, "BOL") == 0 || MdaUtils.compareTo(cortyp, "AIB") == 0) {
                                        v23hOK = true;
                                    }
                                    // DNGDEV.002160  - DTA G06 with SWIFT Standard 2020
                                    if (MdaUtils.compareTo(cortyp, "DTG") == 0) {
                                        v23hOK = true;
                                    }
                                    break;
                                case "DTASTATU":
                                    // DNGDEV.002858: Donot allow old codes for BOL-Messages after SR2020
                                    if (MdaUtils.compareTo(cortyp, "DTA") == 0 || MdaUtils.compareTo(cortyp, "DTE") == 0 || MdaUtils.compareTo(cortyp, "TCO") == 0) {
                                        v23hOK = true;
                                    }
                                    // DNGDEV.002160  - DTA G06 with SWIFT Standard 2020
                                    if (MdaUtils.compareTo(cortyp, "DTG") == 0) {
                                        v23hOK = true;
                                    }
                                    break;
                                case "DTABESTA":
                                case "DTAFINAN":
                                    if (MdaUtils.compareTo(cortyp, "DTE") == 0 || MdaUtils.compareTo(cortyp, "TCO") == 0) {
                                        v23hOK = true;
                                    }
                                    break;
                                case "DTAKORRE":
                                    // DNGDEV.002858: Donot allow old codes for BOL-Messages after SR2020
                                    if (MdaUtils.compareTo(cortyp, "DTA") == 0 || MdaUtils.compareTo(cortyp, "TCO") == 0) {
                                        v23hOK = true;
                                    }
                                    // DNGDEV.002160  - DTA G06 with SWIFT Standard 2020
                                    if (MdaUtils.compareTo(cortyp, "DTG") == 0) {
                                        v23hOK = true;
                                    }
                                    break;
                                case "ISSAMEND":
                                    if (MdaUtils.compareTo(cortyp, "SWT") == 0 || MdaUtils.compareTo(cortyp, "BOL") == 0) {
                                        v23hOK = true;
                                    }
                                    // DNGDEV.002835
                                    break;
                                case "CLSVCLOS":
                                case "CLSVOPEN":
                                case "FRAUDMSG":
                                case "ISSUANCE":
                                case "REIMBURS":
                                case "REQAMEND":
                                case "REQFINAN":
                                case "REQISSUE":
                                case "TRANSFER":
                                case "PREDENOT":
                                    // DNGDEV.002858: Allow codes for BOL-Messages
                                    if (MdaUtils.compareTo(cortyp, "SWT") == 0 || MdaUtils.compareTo(cortyp, "AIB") == 0 || MdaUtils.compareTo(cortyp, "BOL") == 0) {
                                        v23hOK = true;
                                    }
                                    break;
                                case "ADV":
                                    // DNGDEV.002858: Donot allow old codes for BOL-Messages after SR2020
                                    break;
                                case "CNF":
                                case "STA":
                                    if (MdaUtils.compareTo(cortyp, "BOL") == 0) {
                                        v23hOK = true;
                                    }
                                    break;
                                case "CONFIRM":
                                case "INFSTATU":
                                case "REQSTATU":
                                    // DNGDEV.002858: Allow codes for BOL-Messages
                                    if (MdaUtils.compareTo(cortyp, "BOL") == 0) {
                                        v23hOK = true;
                                    }
                                    break;
                                case "REXTMATU":
                                    // DNGDEV.004338
                                    if (MdaUtils.compareTo(cortyp, "SWT") == 0) {
                                        v23hOK = true;
                                    }
                                    break;
                            }
                        }
                    }
                }
            }
            // DNGDEV.001370
            // If no message will be created, all functions are allowed
            if (!v23hOK && !MdaUtils.isEmpty(cortyp)) {
                return ValidResult.build(false, getI18NString("fremsg", "CT000106"));
            }
        }
        return null;
    }

    /**
     * source:fremsg.0047.script
     */
//    @Validate(path = "fremsg.swiadd.newmatdat")
//    public ValidResult checkSwiaddNewmatdatN1000(FremsgVo fremsgVo) {
//        if (MdaUtils.compareTo(fremsgVo.getTag23h(), "REXTMATU") == 0) {
//            if (MdaUtils.isEmpty(fremsgVo.getSwiadd().getNewmatdat())) {
//                return errorMandatory();
//            }
//        }
//        return null;
//    }

    /**
     * source:fremsg.0059.script
     */
    @Warning(path = "fremsg.strinf")
    public WarningResult checkStrinfN1000(FremsgVo fremsgVo) {
        String wrkBlock = "";
        String strinfBlock = "";
        // STRINF is not mandatory for Advice of Auto Renewal
        if (MdaUtils.compareTo(fremsgVo.getSndmt(), "AVN") != 0 && MdaUtils.compareTo(fremsgVo.getSndmt(), "SAN") != 0) {
            if (MdaUtils.isEmpty(fremsgVo.getStrinf())) {
                return WarningResult.buildEmpty("STRINFLEN");
            } else {
                // if messagetype query or answer, tag 79 must have the dimension 35x50x
                if (MdaUtils.compareTo(fremsgVo.getSndmt(), "92") == 0 || MdaUtils.compareTo(fremsgVo.getSndmt(), "95") == 0 || MdaUtils.compareTo(fremsgVo.getSndmt(), "96") == 0) {
                    wrkBlock = StringUtils.convertBlock(fremsgVo.getStrinf(), 999, 50); // DNGDEV.000691.ok - as charset of x9y not changed
                    strinfBlock = StringUtils.convertBlock(fremsgVo.getStrinf(), 35, 50); // DNGDEV.000691.ok - as charset of x9y not changed
                    if (MdaUtils.compareTo(strinfBlock, wrkBlock) != 0) {
                        return WarningResult.build("STRINFLEN", getI18NString("fremsg", "CT000061"));
                    }
                }
            }
        }
        return WarningResult.buildEmpty("STRINFLEN");
    }

    /**
     * source:fremsg.0061.script
     */
    @Validate(path = "fremsg.reldat")
    public ValidResult checkReldatN1000(FremsgVo fremsgVo) {
        //Date is mandatory as it is required for Letter and SWIFT messages
        if (MdaUtils.isEmpty(fremsgVo.getReldat())) {

            if (MdaUtils.compareTo(fremsgVo.getSndmt(), "92") == 0) {
                return errorMandatory();
            }else if (MdaUtils.compareTo(fremsgVo.getSndmt(), "96") == 0) {
                return errorMandatory();
            }  // not mandatory

        }
        if (Dates.diff(fremsgVo.getReldat(), Dates.today()) > 0) {
            return ValidResult.build(false, getI18NString("fremsg", "CT000045"));
        }
        return null;
    }

    /**
     * source:fremsg.0066.script
     */
    @Validate(path = "fremsg.fulmt")
    public ValidResult checkFulmtN1000(FremsgVo fremsgVo) {
        // an empty message type is not allowed
        if ("99,59".contains(fremsgVo.getSndmt())) {
            if (MdaUtils.isEmpty(fremsgVo.getFulmt())) {
                return errorMandatory();
            }
        }
        return null;
    }

    /**
     * source:fremsg.0069.script
     */
    @Warning(path = "fremsg.sndmt")
    public WarningResult checkSndmtN1100(FremsgVo fremsgVo) {
        //! check if there is a need to use "Anxillary Trade Structured Message" for DTA and DTG
        //DOS5LBW.104579
        String warningText = "";
        int gridCnt = 0;
        String strCortyp = "";
        if (!(MdaUtils.compareTo(fremsgVo.getSndmt(), "59") == 0)) {
            // DNGDEV.002160 - DTG G06: Set warning so the user might use the correct SNDMT
            String bus = SettleContext.getUserSession().getAtp().getBus();
            if (MdaUtils.compareTo(bus, "LI") == 0 || MdaUtils.compareTo(bus, "GI") == 0 || MdaUtils.compareTo(bus, "GC") == 0) {
                if (!MdaUtils.isEmpty(fremsgVo.getStrinf())) {
                    BaseTransactionVo parent = (BaseTransactionVo) getParent();
                    for (DoceotVo doceotVo : parent.getDoceot()) {
                        // DNGDEV.002160 - DTG G06: Set warning so the user might use the correct SNDMT
                        strCortyp = doceotVo.getCortyp();
                        if (MdaUtils.compareTo(strCortyp, "DTA") == 0 || (MdaUtils.compareTo(strCortyp, "DTG") == 0)) {
                            if (Strings.pos(doceotVo.getId(), "FRE1") > 0) {
                                warningText = getI18NString("fremsg", "CT000139");
                            } else {
                                warningText = getI18NString("fremsg", "CT000138");
                            }
                            break;
                        }
                    }
                }
            }
        }
        return WarningResult.build("MT799WarningForDTALiGiGc", warningText);
    }

    /**
     * source:fremsg.0070.script
     */
    @Validate(path = "fremsg.strinf")
    public ValidResult checkStrinfN1500(FremsgVo fremsgVo) {
        //dngdev.001640
        if (MdaUtils.compareTo(fremsgVo.getSndmt(), "92") == 0) {
            if (!MdaUtils.isEmpty(fremsgVo.getStrinf())) {
                // DO5DOS.006583
                // check field for codes of Tag75/ MTn95
                // 2nd argument = FALSE: User need not use a code!
                String errorMsg = trnmodService.checkSWTCode(fremsgVo.getStrinf(), false, "79", getOutMT(fremsgVo), true, "", 35, 50);
                if (StringUtils.isNotEmpty(errorMsg)) {
                    return ValidResult.build(false, errorMsg);
                }
            }
        }
        return null;
    }

    /**
     * source:fremsg.0058.script
     */
    public String getOutMT(FremsgVo fremsgVo) {
        //! Get MT that is really used within the outgoing Swift message (original).
        // check if SNDMT is consists of letters only. In this case use 99
        int len = Strings.len(fremsgVo.getSndmt());
        String sndmt = fremsgVo.getSndmt();
        for (int i = 1; i <= len; i++) {
            if (Strings.pos("0123456789", Strings.mid(sndmt, i, 1)) == 0) {
                // No numeric character found, so use "99"
                // only letters found so use "99"
                sndmt = "99";
                break;
            }
        }
        // dngdev.002002 Add SD
        String mt = "";
        switch (SettleContext.getUserSession().getAtp().getBus()) {
            case "CP":
                mt = "1" + sndmt;
                break;
            case "BO":
            case "BC":
            case "CH":
                mt = "4" + sndmt;
                break;
            case "LE":
            case "LI":
            case "BR":
            case "BE":
            case "GI":
            case "GC":
            case "LT":
            case "BT":
            case "RM":
            case "RC":
            case "BP":
            case "TR":
            case "FS":
            case "FP":
            case "PA":
            case "SD":
                //case  "MC":
            case "GE":
                mt = "7" + sndmt;
                break;
            case "MC":
                mt = "9" + sndmt;
                break;
            default:
                mt = "9" + sndmt;
        }
        // check 1st digit
        Argument<String> mtBox = new Argument<>("", mt);
        trnmodService.getCommonGroupMt(mtBox);

        mt = mtBox.value;

        // set MT for Free Correspondence if "MT to Send" is changed by user manually
        if (!MdaUtils.isEmpty(fremsgVo.getFulmt())) {
            // set MT ($MT) if SNDMT=99 to value of FULMT
            // set to MT 199/ 299/ 499 or 799
            mt = fremsgVo.getFulmt();
        }
        // set 1st digit of "Send MT" ($conmt) depending on "Related MT" if available
        String v1stOfRelMT = "";
        String endOfSndMT = "";
        if (!MdaUtils.isEmpty(fremsgVo.getRelmt())) {
            v1stOfRelMT = Strings.mid(fremsgVo.getRelmt(), 1, 1);
            endOfSndMT = Strings.mid(mt, 2, 2);
            mt = v1stOfRelMT + endOfSndMT;
        }
        return mt;

    }

    /**
     * source:fremsg.0078.script
     */
    @Validate(path = "fremsg.tag23xblock")
    public ValidResult checkTag23xblockN1000(FremsgVo fremsgVo) {
        if (!MdaUtils.isEmpty(fremsgVo.getTag23x())) {
            if (MdaUtils.isEmpty(fremsgVo.getTag23xblock())) {
                return errorMandatory();
            }
        }
        return null;
    }

    /**
     * source:fremsg.0080.script
     */
    //前端已添加相关校验，将此校验去掉
//    @Validate(path = "fremsg.strinf")
//    public ValidResult checkStrinfN100(FremsgVo fremsgVo) {
//        //根据业务要求
//        if (!MdaUtils.isEmpty(fremsgVo.getStrinf())) {
//            return characterX(fremsgVo.getStrinf());
//        }
//        return null;
//    }

}
