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

import com.brilliance.isc.bo.bop.jsh.Dbjgrp;
import com.brilliance.isc.bo.bop.jsh.Dbwgrp;
import com.brilliance.isc.common.jshmod.vo.Jshmod;
import com.brilliance.isc.common.jshmod.vo.JshmodRequest;
import com.brilliance.isc.common.setglg.vo.SetglgVo;
import com.brilliance.isc.common.setgll.vo.SetgllVo;
import com.brilliance.isc.common.transaction.newcheck.*;
import com.brilliance.isc.mda.dao.ActkghMapper;
import com.brilliance.isc.mda.dao.BopcodMapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;

/**
 * RMB报送检核
 */
@Component
public class JshmodValidator extends AbstractModuleValidator<JshmodRequest> {

    @Autowired
    private ActkghMapper actkghMapper;

    @Autowired
    private BopcodMapper bopcodMapper;

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

    @Validate(path = "jshmod.dbjgrp.bas.custcod")
    public ValidResult checkDbjCustcod(JshmodRequest jshmodRequest) {
        Jshmod jshmod = jshmodRequest.getJshmod();
        String szflg = jshmod.getSzflg();
        if ("1".equals(szflg)) {
            String custype = jshmod.getDbjgrp().getBas().getCustype();
            if ("C".equals(custype)) {
                String custcod = jshmod.getDbjgrp().getBas().getCustcod();
                if (!zzjgdmCheck(custcod)) {
                    return ValidResult.build(false, "代码校验失败");
                }
            }
        }
        return null;
    }

    @Validate(path = "jshmod.dbwgrp.bas.custcod")
    public ValidResult checkDbwCustcod(JshmodRequest jshmodRequest) {
        Jshmod jshmod = jshmodRequest.getJshmod();
        String szflg = jshmod.getSzflg();
        if ("2".equals(szflg)) {
            String custype = jshmod.getDbwgrp().getBas().getCustype();
            if ("C".equals(custype)) {
                String custcod = jshmod.getDbwgrp().getBas().getCustcod();
                if (!zzjgdmCheck(custcod)) {
                    return ValidResult.build(false, "代码校验失败");
                }
            }
        }
        return null;
    }

    private boolean zzjgdmCheck(String custcod) {
        if (custcod.length() != 9) {
            return false;
        }
        String table = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        int[] wi = {3, 7, 9, 10, 5, 8, 4, 2};
        int vmac = 0;
        for (int i = 0; i < 8; i++) {
            char c = custcod.charAt(i);
            int pos = table.indexOf(c);
            if (pos < 0) {
                return false;
            }
            vmac += pos * wi[i];
        }
        int macint = 11 - vmac % 11;
        String lastChar = custcod.substring(8);
        String mac = (macint == 11) ? "0" : (macint == 10) ? "X" : String.valueOf(macint);
        return mac.equals(lastChar);
    }

    @Validate(path = "jshmod.dbjgrp.bas.fcyacc")
    public ValidResult checkDbjFcyacc(JshmodRequest jshmodRequest) {
        Dbjgrp dbjgrp = jshmodRequest.getJshmod().getDbjgrp();
        String szflg = jshmodRequest.getJshmod().getSzflg();
        return "1".equals(szflg) ? checkFcyacc(dbjgrp.getBas().getFcyacc()) : null;
    }

    @Validate(path = "jshmod.dbwgrp.bas.fcyacc")
    public ValidResult checkDbwFcyacc(JshmodRequest jshmodRequest) {
        Dbwgrp dbwgrp = jshmodRequest.getJshmod().getDbwgrp();
        String szflg = jshmodRequest.getJshmod().getSzflg();
        return "2".equals(szflg) ? checkFcyacc(dbwgrp.getBas().getFcyacc()) : null;
    }

    private ValidResult checkFcyacc(String fcyacc) {
        if (StringUtils.isEmpty(fcyacc)) {
            return ValidResult.build(false, "必输项");
        } else {
            int count = actkghMapper.queryByAccountno(fcyacc);
            if (count < 1) {
                return ValidResult.build(false, "外汇账户尚未报送至外汇局外汇账户系统， 待补报外汇账户数据后再报送账户内结售汇数据");
            }
        }
        return null;
    }

    @Validate(path = "jshmod.dbjgrp.vrf.txcode")
    public ValidResult checkDbjTxcode(JshmodRequest jshmodRequest) {
        Jshmod jshmod = jshmodRequest.getJshmod();
        String szflg = jshmod.getSzflg();
        String txcode = jshmod.getDbjgrp().getVrf().getTxcode();
        if ("1".equals(szflg)) {
            if (txcode.length() == 6 && txcode.charAt(0) != 'D') {
                String jshType = getJSHType(jshmodRequest.getSetglg());
                if (StringUtils.isNotEmpty(jshType) && !checkTxcode(txcode, jshType)) {
                    return ValidResult.build(false, "交易编码与结汇类型不一致，请检查！");
                }
            }
            if ("Y".equals(jshmod.getZbxmszh())) {
                if (!isZbxmCod(txcode)) {
                    return ValidResult.build(false, "资本项目数字化请录入资本项目相关的交易编码");
                }
            }
        }
        return null;
    }

    @Validate(path = "jshmod.dbwgrp.vrf.txcode")
    public ValidResult checkDbwTxcode(JshmodRequest jshmodRequest) {
        Jshmod jshmod = jshmodRequest.getJshmod();
        String szflg = jshmod.getSzflg();
        String txcode = jshmod.getDbwgrp().getVrf().getTxcode();
        if ("2".equals(szflg)) {
            if (txcode.length() == 6 && txcode.charAt(0) != 'D') {
                String jshType = getJSHType(jshmodRequest.getSetglg());
                if (StringUtils.isNotEmpty(jshType) && !checkTxcode(txcode, jshType)) {
                    return ValidResult.build(false, "交易编码与售汇类型不一致，请检查！");
                }
            }
            if ("Y".equals(jshmod.getZbxmszh())) {
                if (!isZbxmCod(txcode)) {
                    return ValidResult.build(false, "资本项目数字化请录入资本项目相关的交易编码");
                }
            }
        }
        return null;
    }

    @Warning(path = "jshmod.dbjgrp.vrf.txcode")
    public WarningResult warningDbjTxcode(JshmodRequest jshmodRequest) {
        Jshmod jshmod = jshmodRequest.getJshmod();
        String szflg = jshmod.getSzflg();
        String txcode = jshmod.getDbjgrp().getVrf().getTxcode();
        if ("1".equals(szflg)) {
            if (!"Y".equals(jshmod.getZbxmszh()) && isZbxmCod(txcode)) {
                return WarningResult.build("zbxmNWarning", "交易编码为资本项目相关，请确认是否为资本项目数字化");
            }
        }
        return WarningResult.buildEmpty("zbxmNWarning");
    }

    @Warning(path = "jshmod.dbwgrp.vrf.txcode")
    public WarningResult warningDbwTxcode(JshmodRequest jshmodRequest) {
        Jshmod jshmod = jshmodRequest.getJshmod();
        String szflg = jshmod.getSzflg();
        String txcode = jshmod.getDbwgrp().getVrf().getTxcode();
        if ("2".equals(szflg)) {
            if (!"Y".equals(jshmod.getZbxmszh()) && isZbxmCod(txcode)) {
                return WarningResult.build("zbxmNWarning", "交易编码为资本项目相关，请确认是否为资本项目数字化");
            }
        }
        return WarningResult.buildEmpty("zbxmNWarning");
    }

    @Warning(path = "jshmod.dbjgrp.vrf.regno")
    public WarningResult warningDbjRegno(JshmodRequest jshmodRequest) {
        Jshmod jshmod = jshmodRequest.getJshmod();
        String szflg = jshmod.getSzflg();
        String txcode = jshmod.getDbjgrp().getVrf().getTxcode();
        if ("1".equals(szflg)) {
            if ("Y".equals(jshmod.getZbxmszh()) && isZbxmCod(txcode)) {
                String regno = jshmod.getDbjgrp().getVrf().getRegno();
                List<String> list = Arrays.asList("226000", "322041", "322042", "322043", "322049", "323010", "323020");
                if ("N/A".equals(regno) && list.contains(txcode)) {
                    return WarningResult.build("zbxmYWarning", "该笔为资本数字化业务，请确认批件号栏位为N/A是否正确");
                }
            }
        }
        return WarningResult.buildEmpty("zbxmNWarning");
    }

    @Warning(path = "jshmod.dbwgrp.vrf.regno")
    public WarningResult warningDbwRegno(JshmodRequest jshmodRequest) {
        Jshmod jshmod = jshmodRequest.getJshmod();
        String szflg = jshmod.getSzflg();
        String txcode = jshmod.getDbwgrp().getVrf().getTxcode();
        if ("2".equals(szflg)) {
            if ("Y".equals(jshmod.getZbxmszh()) && isZbxmCod(txcode)) {
                String regno = jshmod.getDbwgrp().getVrf().getRegno();
                List<String> list = Arrays.asList("226000", "322041", "322042", "322043", "322049", "323010", "323020");
                if ("N/A".equals(regno) && list.contains(txcode)) {
                    return WarningResult.build("zbxmYWarning", "该笔为资本数字化业务，请确认批件号栏位为N/A是否正确");
                }
            }
        }
        return WarningResult.buildEmpty("zbxmNWarning");
    }

    private boolean isZbxmCod(String txcode) {
        List<String> zbxmCod = bopcodMapper.selectZbxmCod();
        return !zbxmCod.isEmpty() && zbxmCod.contains(txcode);
    }

    private String getJSHType(SetglgVo setglg) {
        String jshType = null;
        for (SetgllVo setgll : setglg.getSetgll()) {
            String cur = setgll.getCur();
            String acccur = setgll.getAcccur();
            BigDecimal amt = setgll.getAmt();
            if (!StringUtils.equals(cur, acccur)) {
                int compare = amt.compareTo(BigDecimal.ZERO);
                if (("CNY".equals(acccur) && compare < 0) || (!"CNY".equals(acccur) && compare > 0)) {
                    jshType = setgll.getTrdint();
                } else {
                    jshType = setgll.getTrdout();
                }
            }
        }
        return jshType;
    }

    private boolean checkTxcode(String txcode, String jshType) {
        boolean rtn = true;
        String txt;
        switch (jshType) {
            //货物贸易
            case "110":
                txt = "-121010-121020-121030-121040-121080-121090-121990-122010-122020-122030-122990-921010-921020-921030-";
                break;
            //货物贸易
            case "310":
                txt = "-121010-121020-121030-121040-121080-121100-121110-121990-122010-122020-122030-122990-921010-921020-921030-";
                break;
            //运输
            case "121":
            case "321":
                txt = "-222011-222012-222013-222014-222019-222021-222022-222023-222024-222029-222031-222032-222033-222034-222039-222040-";
                break;
            //旅游
            case "122":
            case "322":
                txt = "-223010-223021-223022-223023-223029-";
                break;
            //金融和保险服务
            case "123":
            case "323":
                txt = "-225010-225021-225022-225029-225030-225040-225050-226000-";
                break;
            //专有权利使用费和特许费
            case "124":
            case "324":
                txt = "-231010-231020-231030-231040-231990-";
                break;
            //咨询服务
            case "125":
            case "325":
//                txt = "-228021-228022-228023-";
                //  125、325：增加“228024	广告服务”、“228025	展会服务”、“228026	市场调查、民意测验服务”；
                txt = "-228021-228022-228023-228024-228025-228026-";
                break;
            //其他服务
            case "126":
            case "326":
//                txt = "-221000-224010-224020-227010-227020-227030-228010-228024-228025-228026-228031-228032-228033-228039-228040-228050-228060-228990-229010-229020-229030-229990-230000-232000";
                //126、326：取消“228024	广告服务”、“228025	展会服务”、“228026	市场调查、民意测验服务”。
                txt = "-221000-224010-224020-227010-227020-227030-228010-228031-228032-228033-228039-228040-228050-228060-228990-229010-229020-229030-229990-230000-232000-";
                break;
            //职工报酬和赡家款
            case "131":
            case "331":
//                txt = "-321000-";
                //    131、331：增加“421010	个人间捐赠及无偿援助。
                txt = "-321000-421010-";
                break;
            //投资收益
            case "332":
                txt = "-322011-322012-322013-322014-322021-322022-322023-322031-322032-322033-322034-322041-322042-322043-322049-323010-323020-922090-";
                break;
            //投资收益
            case "132":
                txt = "-322011-322012-322013-322014-322021-322022-322023-322031-322032-322033-322034-322041-322042-322043-322049-323010-323020-922010-922090-";
                break;
            //其他经常转移
            case "133":
            case "333":
                txt = "-421010-421020-421990-422000-423010-423020-424000-";
                break;
            //资本账户
            case "210":
            case "410":
//                txt = "-521020-521030-521990-522000-";
                //210、410：增加“521010债务减免”。
                txt = "-521010-521020-521030-521990-522000-";
                break;
            //投资资本金
            case "221":
//                txt = "-622011-622012-622013-622014-622015-622016-623012-923010-923020-";
                //221：删除“622015对境外母公司的股权投资的撤回（逆向股权投资的撤回）/外商投资企业对境外母公司的股权投资（逆向股权投资）”，
                //增加“621015	接受境外子公司的股权投资（逆向股权投资）/境外子公司撤回对境内母公司的股权投资（逆向股权投资的撤回）”；
                txt = "-621015-622011-622012-622013-622014-622016-623012-923010-923020-";
                break;
            //投资资本金/直接投资撤资
            case "421":
            case "222":
//                txt = "-621011-621012-621013-621014-621015-621016-621030-623011-";
                //421、222删除“621015	接受境外子公司的股权投资（逆向股权投资）/境外子公司撤回对境内母公司的股权投资（逆向股权投资的撤回）”；
                //增加“622015对境外母公司的股权投资的撤回（逆向股权投资的撤回）/外商投资企业对境外母公司的股权投资（逆向股权投资）”。
                txt = "-621011-621012-621013-621014-621016-621030-622015-623011-";
                break;
            //直接投资撤资
            case "422":
//                txt = "-622011-622012-622013-622014-622015-622016-623012-";
                //422：删除“622015对境外母公司的股权投资的撤回（逆向股权投资的撤回）/外商投资企业对境外母公司的股权投资（逆向股权投资）”，
                //增加“621015	接受境外子公司的股权投资（逆向股权投资）/境外子公司撤回对境内母公司的股权投资（逆向股权投资的撤回）”
                //增加“923010代外国投资者划入/划出投资款”、“923020境内投资者投资款划入/划出”。
                txt = "-621015-622011-622012-622013-622014-622016-623012-923010-923020-";
                break;
            //房地产
            case "223":
            case "423":
                txt = "-622030-";
                break;
            //其他直接投资
            case "22A":
            case "42A":
                txt = "-621021-621022-622021-622022-623021-623022-923090-";
                break;
            //对境外证券投资撤回/对境外证券投资
            case "231":
            case "431":
                txt = "-721010-721020-721050-722010-722040-723011-723014-723021-723024-724000-";
                break;
            //证券筹资/证券投资撤出
            case "232":
            case "432":
                txt = "-721030-721040-722020-722030-723012-723013-723022-723023-";
                break;
            //跨境贷款
            case "441":
//                txt = "-821020-822020-923010-923020-";
                //441：删除“923010代外国投资者划入/划出投资款”、“923020境内投资者投资款划入/划出”。
                txt = "-821020-822020-";
                break;
            //跨境贷款
            case "241":
                txt = "-821020-822020-";
                break;
            //其他投资
            case "24A":
                txt = "-821010-821030-821990-822010-822030-822990-929040-929050-929060-929080-929090-999998-999999-";
                break;
            //其他投资
            case "44A":
                txt = "-821010-821030-821990-822010-822030-822990-929040-929050-929060-929070-929080-929090-999998-999999-";
                break;
            //国内外汇贷款
            case "250":
            case "450":
                txt = "-924010-924020-924030-924090--";
                break;
            //其他
            case "270":
                txt = "-925010-925020-929010-929020-929030-";
                break;
            //其他
            case "470":
                txt = "-925010-925020-929010-929030-";
                break;
            //外债转贷款
            case "242":
            case "442":
                //资本金（营运资金）/金融机构资金本外币转换
            case "261":
            case "461":
                //代债务人结汇/代债务人售汇
            case "262":
            case "462":
                //其他金融机构资本金本外币转换
            case "26A":
            case "46A":
            default:
                txt = "";
        }
        if (StringUtils.isNotEmpty(txt)) {
            rtn = txt.contains(txcode);
        }

        return rtn;
    }

    @Validate(path = "jshmod.dbjgrp.vrf.regno")
    public ValidResult checkDbjRegno(JshmodRequest jshmodRequest) {
        Jshmod jshmod = jshmodRequest.getJshmod();
        String szflg = jshmod.getSzflg();
        String txcode = jshmod.getDbjgrp().getVrf().getTxcode();
        String regno = jshmod.getDbjgrp().getVrf().getRegno();
        if ("1".equals(szflg)) {
            String type = bopcodMapper.getBopcodType("I", txcode);
            if ("C".equals(type) && StringUtils.isEmpty(regno)) {
                return ValidResult.build(false, "此数据项为必输项，如为空请填写N/A！");
            }
        }
        return null;
    }

    @Validate(path = "jshmod.dbwgrp.vrf.regno")
    public ValidResult checkDbwRegno(JshmodRequest jshmodRequest) {
        Jshmod jshmod = jshmodRequest.getJshmod();
        String szflg = jshmod.getSzflg();
        String txcode = jshmod.getDbwgrp().getVrf().getTxcode();
        String regno = jshmod.getDbwgrp().getVrf().getRegno();
        if ("2".equals(szflg)) {
            String type = bopcodMapper.getBopcodType("O", txcode);
            if ("C".equals(type) && StringUtils.isEmpty(regno)) {
                return ValidResult.build(false, "此数据项为必输项，如为空请填写N/A！");
            }
        }
        return null;
    }

    @Validate(path = "jshmod.dbjgrp.vrf.usetype")
    public ValidResult checkDbjUsetype(JshmodRequest jshmodRequest) {
        Jshmod jshmod = jshmodRequest.getJshmod();
        String szflg = jshmod.getSzflg();
        String txcode = jshmod.getDbjgrp().getVrf().getTxcode();
        String usetype = jshmod.getDbjgrp().getVrf().getUsetype();
        if ("1".equals(szflg) && StringUtils.isNotEmpty(txcode)) {
            String type = bopcodMapper.getBopcodType("I", txcode);
            if ("C".equals(type) && StringUtils.isEmpty(usetype)) {
                return ValidResult.build(false, "当交易编码为资本类型时，此项为必输项！");
            }
        }
        return null;
    }

}
