package com.brilliance.isc.common.transaction.newcheck.trtcre;

import com.brilliance.isc.bo.Bopcod;
import com.brilliance.isc.bo.Bopcty;
import com.brilliance.isc.bo.Cnycty;
import com.brilliance.isc.bo.model.Trtcre;
import com.brilliance.isc.common.cbsmod.service.XrtmodService;
import com.brilliance.isc.common.component.TrtmodComponent;
import com.brilliance.isc.common.context.SettleContext;
import com.brilliance.isc.common.finmod.service.FinmodService;
import com.brilliance.isc.common.setmod.service.SetmodService;
import com.brilliance.isc.common.transaction.newcheck.*;
import com.brilliance.isc.common.util.StringUtils;
import com.brilliance.isc.common.util.Utils;
import com.brilliance.isc.mda.dao.BopcodMapper;
import com.brilliance.isc.mda.dao.BopctyMapper;
import com.brilliance.isc.mda.dao.CnyctyMapper;
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 org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.time.temporal.Temporal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Component
public class TrtcreValidator extends AbstractModuleValidator<Trtcre> {

    private static final String TRTCRE_CHECK_PREFIX = "trtcre.";

    @Autowired
    private TrtmodComponent trtmodComponent;

    @Autowired
    private XrtmodService xrtmodService;

    @Autowired
    private SetmodService setmodService;

    @Autowired
    private FinmodService finmodService;

    @Autowired
    private TrtpValidator trtpValidator;

    @Autowired
    private FinmodValidator finmodValidator;

    @Autowired
    private CnyctyMapper cnyctyMapper;

    @Autowired
    private BopctyMapper bopctyMapper;

    @Autowired
    private BopcodMapper bopcodMapper;

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

    @Override
    public Map<String, String> validate(Trtcre vo) {
        Map<String, String> maps = new HashMap<>();
        if ("X".equalsIgnoreCase(vo.getCrefinflg())) {
            maps.putAll(super.validate(vo));

            //验证Trtp模型
            trtpValidator.registerParent(vo.getTrdgrp());
            Map<String, String> trtpMaps = trtpValidator.validate(vo.getTrtp());
            for (String key : trtpMaps.keySet()) {
                maps.put(TRTCRE_CHECK_PREFIX + key, trtpMaps.get(key));
            }
            trtpValidator.removeTl();

            //验证finmod模型
            Map<String, String> finmodMaps = finmodValidator.validate(vo.getFinmod());
            for (String key : finmodMaps.keySet()) {
                maps.put(TRTCRE_CHECK_PREFIX + key, finmodMaps.get(key));
            }
        }
        return maps;
    }

    /**
     *   source:trtcre.0005.script
     */
    @Validate(path = "trtcre.trdgrp.rec.issdat")
    public ValidResult checkTrdgrpRecIssdatN1000(Trtcre trtcreVo){
        if(isCreateFinance(trtcreVo)) {
            if(MdaUtils.isEmpty(trtcreVo.getTrdgrp().getRec().getIssdat())) {
                return errorMandatory();
            }
        }
        return null;
    }

    /**
     *   source:trtcre.0006.script
     */
    @Validate(path = "trtcre.trdgrp.rec.matdat")
    public ValidResult checkTrdgrpRecMatdatN1000(Trtcre trtcreVo){
        int d = 0;
        if(isCreateFinance(trtcreVo)) {
            if(MdaUtils.isEmpty(trtcreVo.getTrdgrp().getRec().getMatdat())) {
                return errorMandatory();
            }
            if(MdaUtils.compareTo(trtcreVo.getTrdgrp().getRec().getFintyp(), "PCL") == 0) {
                Date expdat = trtcreVo.getRec().getExpdat();
                if(Dates.diff(trtcreVo.getTrdgrp().getRec().getMatdat(), expdat)>0 ) {
                    return ValidResult.build(false, "Maturity date of Packing loan cannot be after the expiry of LC");
                }
            }
        }
        return null;
    }

    @Warning(path = "trtcre.trdgrp.rec.matdat", enable = "N")
    public WarningResult warningTrdgrpRecMatdat(Trtcre trtcreVo) {
        if (isCreateFinance(trtcreVo)) {
            if (trtcreVo.getTrdgrp().getRec().getMatdat() != null) {
                int days = Dates.diff(trtcreVo.getTrdgrp().getRec().getMatdat(), trtcreVo.getTrdgrp().getRec().getStttendat());
                String txt = trtmodComponent.chktotten(days, trtcreVo.getTrdgrp().getFip().getPtyinr());
                if (StringUtils.isNotEmpty(txt)) {
                    return WarningResult.build("SUBCHECKMATDAT", txt);
                }
            }
        }
        return WarningResult.buildEmpty("SUBCHECKMATDAT");
    }

    @Warning(path = "trtcre.trdgrp.rec.matdat")
    public WarningResult warningTrdgrpRecMatdat1(Trtcre trtcreVo) {
        if(!MdaUtils.isEmpty(trtcreVo.getTrdgrp().getRec().getMatdat())) {
            if (setmodService.isHoliday(trtcreVo.getOricur(), trtcreVo.getTrdgrp().getRec().getMatdat())) {
                return WarningResult.build("SUBCHECKMATDAT1", Strings.getText("融资到期日$1为节假日", Utils.fmtDate(trtcreVo.getTrdgrp().getRec().getMatdat(), "yyyy-MM-dd")));
            }
        }
        return WarningResult.buildEmpty("SUBCHECKMATDAT1");
    }

    /**
     *   source:trtcre.0007.script
     */
    @Validate(path = "trtcre.trdgrp.rec.stttendat")
    public ValidResult checkTrdgrpRecStttendatN1000(Trtcre trtcreVo){
        if(isCreateFinance(trtcreVo)) {
            if(MdaUtils.isEmpty(trtcreVo.getTrdgrp().getRec().getStttendat())) {
                return errorMandatory();
            }
        }
        return null;
    }

    /**
     *   source:trtcre.0010.script
     */
    @Warning(path = "trtcre.trdgrp.rec.tenday")
    public WarningResult warningTrdgrpRecTendayN1000(Trtcre trtcreVo){
        if(isCreateFinance(trtcreVo)) {
            String ptyinr = trtcreVo.getTrdgrp().getFip().getPtyinr();
            String txt = trtmodComponent.chktotten((int)trtcreVo.getTrdgrp().getRec().getTenday(), ptyinr);
            if (StringUtils.isNotEmpty(txt)) {
                return WarningResult.build("SUBCHECKTENDAY", txt);
            }
        }
        return WarningResult.buildEmpty("SUBCHECKTENDAY");
    }

    /**
     *   source:trtcre.0016.script
     */
    @Validate(path = "trtcre.trdgrp.cbs.max.cur")
    public ValidResult checkTrdgrpCbsMaxCurN1000(Trtcre trtcreVo){
        BigDecimal rat = null;
        BigDecimal sqrrat = null;
        if(isCreateFinance(trtcreVo)) {
            if(MdaUtils.isEmpty(trtcreVo.getTrdgrp().getCbs().getMax().getCur())) {
                return errorMandatory();
            } else {
                Argument<BigDecimal> ratBox = new Argument<BigDecimal>();
                Argument<BigDecimal> sqrratBox = new Argument<BigDecimal>();
                xrtmodService.getrat(xrtmodService.sysiso(), trtcreVo.getTrdgrp().getCbs().getMax().getCur(), "M", Dates.today(), ratBox, sqrratBox);

                rat = ratBox.value;
                sqrrat = sqrratBox.value;

                if(MdaUtils.isEmpty(rat)) {
                    return ValidResult.build(false, Strings.getText("Please enter an exchange rate for $1", trtcreVo.getTrdgrp().getCbs().getMax().getCur()));
                }
                if(!MdaUtils.isEmpty(trtcreVo.getFinmod().getDinmod().getBizhog()) && MdaUtils.compareTo(trtcreVo.getTrdgrp().getCbs().getMax().getCur(), trtcreVo.getFinmod().getDinmod().getBizhog()) != 0 ) {
                    return ValidResult.build(false, Strings.getText("请保持与定价系统放款的币种$1一致", trtcreVo.getFinmod().getDinmod().getBizhog()));
                }
            }
        }
        return null;
    }

    /**
     *   source:trtcre.0030.script
     */
    @Validate(path = "trtcre.trdgrp.rec.pctfin")
    public ValidResult checkCheckPctFinN1000(Trtcre trtcreVo){
        if(isCreateFinance(trtcreVo)) {
            if(!MdaUtils.isEmpty(trtcreVo.getTrdgrp().getRec().getPctfin())) {
                if( MdaUtils.compareTo(trtcreVo.getTrdgrp().getRec().getPctfin(),100)>0 ) {
                    return ValidResult.build(false, "融资比例不能大于100%");
                } else {
                    if( MdaUtils.isEmpty(trtcreVo.getTrdgrp().getRec().getPctfin()) && MdaUtils.isEmpty(trtcreVo.getTrdgrp().getCbs().getMax().getAmt()) ) {
                        return ValidResult.build(false, "Either percent or amount must be entered");
                    }
                }
            }
        }
        return null;
    }

    /**
     *   source:trtcre.0030.script
     */
    @Validate(path = "trtcre.trdgrp.cbs.max.amt")
    public ValidResult checkCheckAmtN1000(Trtcre trtcreVo){
        if( MdaUtils.compareTo(trtcreVo.getFinmod().getOpnflg(),"Y") == 0 ) {
            if( MdaUtils.compareTo(trtcreVo.getFinmod().getDinmod().getMaxdje(),0) != 0 && MdaUtils.compareTo(trtcreVo.getFinmod().getDinmod().getMindje(),0) != 0 ) {
                if( MdaUtils.compareTo(trtcreVo.getTrdgrp().getCbs().getMax().getAmt(), trtcreVo.getFinmod().getDinmod().getMaxdje())>0 ) {
                    return ValidResult.build(false, "不能大于定价系统最大贷款金额");
                }
                if( MdaUtils.compareTo(trtcreVo.getTrdgrp().getCbs().getMax().getAmt(), trtcreVo.getFinmod().getDinmod().getMindje())<0 ) {
                    return ValidResult.build(false, "不能小于定价系统最小贷款金额");
                }
            }
        }
        return null;
    }

    /**
     *   source:trtcre.0043.script
     */
    @Validate(path = "trtcre.trdgrp.rec.actrat")
    public ValidResult checkTrdgrpRecActratN1000(Trtcre trtcreVo){
        if(isCreateFinance(trtcreVo)) {
            if(MdaUtils.isEmpty(trtcreVo.getTrdgrp().getRec().getActrat())) {
                return errorMandatory();
            }
        }
        return null;
    }

    /**
     *   source:trtcre.0044.script
     */
    @Validate(path = "trtcre.finmod.intprd")
    public ValidResult checkTrtmodFinmodIntprdN1000(Trtcre trtcreVo){
        if(isCreateFinance(trtcreVo)) {
            if( MdaUtils.isEmpty(trtcreVo.getFinmod().getIntprd()) ) {
                return errorMandatory();
            }
        }
        return null;
    }

    /**
     *   source:trtcre.0045.script
     */
    @Validate(path = "trtcre.trdgrp.rec.guaflg")
    public ValidResult checkTrdgrpRecGuaflgN1000(Trtcre trtcreVo){
        if(isCreateFinance(trtcreVo)) {
            if(MdaUtils.isEmpty(trtcreVo.getTrdgrp().getRec().getGuaflg())) {
                return errorMandatory();
            }
        }
        return null;
    }

    /**
     *   source:trtcre.0062.script
     */
    @Validate(path = "trtcre.trdgrp.rec.tenday")
    public ValidResult checkTrdgrpRecTendayN2000(Trtcre trtcreVo){
        if( MdaUtils.compareTo(trtcreVo.getFinmod().getOpnflg(),"Y") == 0 ) {
            if( ! MdaUtils.isEmpty(trtcreVo.getFinmod().getDinmod().getMaxqix()) && ! MdaUtils.isEmpty(trtcreVo.getFinmod().getDinmod().getMinqix()) ) {
                if( trtcreVo.getTrdgrp().getRec().getTenday() > trtcreVo.getFinmod().getDinmod().getMaxqix() ) {
                    return ValidResult.build(false, "不能大于定价系统最大贷款期限");
                }
                if( trtcreVo.getTrdgrp().getRec().getTenday() < trtcreVo.getFinmod().getDinmod().getMinqix() ) {
                    return ValidResult.build(false, "不能小于定价系统最小贷款期限");
                }
            }
        }
        return null;
    }

    @Warning(path = "trtcre.trdgrp.rec.tenday")
    public WarningResult checkTrdgrpRecTenday(Trtcre trtcreVo){
        Date stttendat = trtcreVo.getTrdgrp().getRec().getStttendat();
        Date matdat = trtcreVo.getTrdgrp().getRec().getMatdat();
        int unt = 0;
        if (stttendat != null && matdat != null) {
            if ("CPTOPN".equals(SettleContext.getTransName())) {
                int tenorday = trtcreVo.getTrdgrp().getRec().getTenorday();
                if (tenorday > 0) {
                    matdat = Dates.add(matdat, tenorday);
                }
            }
            //计算是否超过半年
            unt = Utils.calcUnt(stttendat, matdat, "CALMON");
        }
        if (unt > 6) {
            return WarningResult.build("TRNDAYSUBID1", "融资期限超半年，请确认是否完成超权限审批");
        }
        return WarningResult.buildEmpty("TRNDAYSUBID1");
    }

    @Warning(path = "trtcre.trdgrp.rec.tenday")
    public WarningResult checkTrdgrpRecTenday2(Trtcre trtcreVo){
        Date stttendat = trtcreVo.getTrdgrp().getRec().getStttendat();
        Date matdat = trtcreVo.getTrdgrp().getRec().getMatdat();
        int unt = 0;
        if (stttendat != null && matdat != null) {
            //计算是否超过半年
            unt = Utils.calcUnt(stttendat, matdat, "CALMON");
        }
        if (unt > 6 && MdaUtils.compareTo(SettleContext.getTransName(),"BDTSET") == 0) {
            return WarningResult.build("TRNDAYSUBID2", "融资天数应从签订买方押汇合同起算不超过半年！");
        }
        return WarningResult.buildEmpty("TRNDAYSUBID2");
    }
    /**
     *   source:trtcre.0067.script
     */
    @Validate(path = "trtcre.trdgrp.rec.trntyp")
    public ValidResult checkTrdgrpRecTrntypN1000(Trtcre trtcreVo){
        //--zmqzmq--
        if( MdaUtils.compareTo(trtcreVo.getZmqflg(),"X") == 0 ) {
            switch(SettleContext.getDirectTransName()) {
                case "BPTOPN":
                case  "TRTOPN":
                    break;
                case "BRTSET":
                case  "BCTSET":
                case  "BDTSET":
                case  "CPTOPN":
                case  "CPTATO":
                    if(isCreateFinance(trtcreVo)) {
                        if(MdaUtils.isEmpty(trtcreVo.getTrdgrp().getRec().getTrntyp())) {
                            return errorMandatory();
                        } else {
                            List<Bopcod> bopcodList = bopcodMapper.getBopcodByCondition("I", "A", null, trtcreVo.getTrdgrp().getRec().getTrntyp());
                            if (bopcodList == null || bopcodList.size() == 0) {
                                return ValidResult.build(false, "无效的交易性质");
                            }
                        }
                    }
                    break;
            }
        }
        return null;
    }

    /**
     *   source:trtcre.0067.script
     */
    @Validate(path = "trtcre.trdgrp.rec.reccountrycode")
    public ValidResult checkTrdgrpRecCountrycode(Trtcre trtcreVo){
        //--zmqzmq--
        if (StringUtils.isNotEmpty(trtcreVo.getTrdgrp().getRec().getReccountrycode())) {
            if( MdaUtils.compareTo(trtcreVo.getZmqflg(),"X") == 0 ) {
                Cnycty cnycty = cnyctyMapper.getCnyctyByCode(trtcreVo.getTrdgrp().getRec().getReccountrycode());
                if (cnycty == null) {
                    return ValidResult.build(false, "无效的国别代码");
                }
            } else {
                Bopcty bopcty = bopctyMapper.queryBopCod(trtcreVo.getTrdgrp().getRec().getReccountrycode());
                if (bopcty == null) {
                    return ValidResult.build(false, "无效的国别代码");
                }
            }
        }
        return null;
    }

    /**
     *   source:trtcre.0068.script
     */
    @Validate(path = "trtcre.trdgrp.rec.oppacc")
    public ValidResult checkTrdgrpRecOppaccN1000(Trtcre trtcreVo){
        //--zmqzmq---
        if( MdaUtils.compareTo(trtcreVo.getZmqflg(),"X") == 0 ) {
            switch(SettleContext.getDirectTransName()) {
                case "BPTOPN":
                case  "TRTOPN":
                    break;
                case "BRTSET":
                case  "BCTSET":
                case  "BDTSET":
                case  "CPTOPN":
                case  "CPTATO":
                    if(isCreateFinance(trtcreVo)) {
                        if(MdaUtils.isEmpty(trtcreVo.getTrdgrp().getRec().getOppacc())) {
                            return errorMandatory();
                        }
                    }
                    break;
            }
        }
        return null;
    }

    /**
     *   source:trtcre.0074.script
     */
    @Validate(path = "trtcre.trdgrp.rec.invtyp")
    public ValidResult checkTrdgrpRecInvtypN1000(Trtcre trtcreVo){
        if(isCreateFinance(trtcreVo)) {
            if( MdaUtils.isEmpty(trtcreVo.getTrdgrp().getRec().getInvtyp()) ) {
                return errorMandatory();
            }
        }
        return null;
    }

    /**
     *   source:trtmod.0014.script
     *   TRTOPN TRTAME 也需要写此方法
     */
    @Validate(path = "trtcre.trdgrp.rec.lprtyp")
    public ValidResult checkTrdgrpRecLprtypN1000(Trtcre trtcreVo){
        String frame = SettleContext.getDirectTransName();
        if(Strings.pos("-TRTOPN-BRTSET-BCTSET-BDTSET-TRTAME-CPTOPN-CPTATO-", frame) > 0) {
            String jjllgz = "";
            String cur = "";
            Date from = Dates.today();
            Date till = Dates.today();
            switch(frame) {
                /*case "TRTAME":
                    jjllgz = Datas.getContent(this,"\\TRTMOD\\FINMOD\\DINMOD\\JZLLGZ");
                    cur = Datas.getContent(this,"\\TRDGRP\\CBS\\MAX\\CUR");
                    from = Datas.getContentDate(this,"\\TRDGRP\\REC\\STTTENDAT");
                    till = Datas.getContentDate(this,"\\NEWMATDAT");
                    break;*/
                case "TRTOPN":
                case "BRTSET":
                case "BCTSET":
                case "BDTSET":
                case "CPTOPN":
                case "CPTATO":
                    jjllgz = trtcreVo.getFinmod().getDinmod().getJzllgz();
                    cur = trtcreVo.getTrdgrp().getCbs().getMax().getCur();
                    from = trtcreVo.getTrdgrp().getRec().getStttendat();
                    till = trtcreVo.getTrdgrp().getRec().getMatdat();
                    break;
            }
            if(finmodService.isCreFinTrn(trtcreVo.getFinmod())) {
                //基准利率规则=市场LPR基准且币种为人民币时，校验必输
                if( MdaUtils.compareTo(jjllgz,"1") == 0 && MdaUtils.compareTo(cur,"CNY") == 0 ) {
                    if( MdaUtils.isEmpty(trtcreVo.getTrdgrp().getRec().getLprtyp()) ) {
                        return errorMandatory();
                    }
                }
                //当币种不是人民币，或者基准利率准则不是LPR时，市场LPR期限品种字段不能有值
                if( MdaUtils.compareTo(jjllgz,"1") != 0 || MdaUtils.compareTo(cur,"CNY") != 0 ) {
                    if( !MdaUtils.isEmpty(trtcreVo.getTrdgrp().getRec().getLprtyp()) ) {
                        return ValidResult.build(false, "'币种不是人民币或基准利率准则不是市场LPR基准时，该字段不能有值");
                    }
                }
                String idtype = trtcreVo.getIdType();
                Temporal fromDate = LocalDate.parse(Utils.fmtDate(from, "yyyy-MM-dd"));
                Temporal toDate = LocalDate.parse(Utils.fmtDate(till, "yyyy-MM-dd"));
                long tenday = ChronoUnit.YEARS.between(fromDate, toDate);
                if ("Y".equalsIgnoreCase(trtcreVo.getFinmod().getOpnflg())) {
                    if( MdaUtils.compareTo(idtype,"2") == 0) {
                        if( tenday <= 1 && MdaUtils.compareTo(trtcreVo.getTrdgrp().getRec().getLprtyp(),"099") == 0 ) {
                            return ValidResult.build(false, "贷款期限<=1年时，LPR期限品种只能选择1YLPR");
                        }
                        if( tenday > 5 && MdaUtils.compareTo(trtcreVo.getTrdgrp().getRec().getLprtyp(),"001") == 0 ) {
                            return ValidResult.build(false, "贷款期限>5年时，LPR期限品种只能选择5YLPR");
                        }
                    } else {
                        if( MdaUtils.compareTo(trtcreVo.getTrdgrp().getRec().getLprtyp(),"001") == 0 && MdaUtils.compareTo(tenday,5)>0 ) {
                            return ValidResult.build(false, "LPR期限品种为1YLPR但贷款期限大于5年，不允许放款");
                        }
                        if( MdaUtils.compareTo(trtcreVo.getTrdgrp().getRec().getLprtyp(),"099") == 0 && MdaUtils.compareTo(tenday,1)<0 ) {
                            return ValidResult.build(false, "LPR期限品种为5YLPR但贷款期限小于1年，不允许放款");
                        }
                    }
                } else {
                    if(tenday <= 1 && MdaUtils.compareTo(trtcreVo.getTrdgrp().getRec().getLprtyp(),"099") == 0) {
                        return ValidResult.build(false, "贷款期限<=1年时，LPR期限品种只能选择1YLPR");
                    }
                    if(tenday > 5 && MdaUtils.compareTo(trtcreVo.getTrdgrp().getRec().getLprtyp(),"001") == 0) {
                        return ValidResult.build(false, "贷款期限>5年时，LPR期限品种只能选择5YLPR");
                    }
                }
            }
        }
        return null;
    }

    /**
     * 是否创建融资
     * @param trtcreVo
     * @return
     */
    private boolean isCreateFinance(Trtcre trtcreVo) {
        return "X".equalsIgnoreCase(trtcreVo.getCrefinflg());
    }
}
