package com.brilliance.isc.swift.objmtconvert.util;

import cn.hutool.core.lang.Assert;
import com.brilliance.isc.swift.objmtconvert.annotation.Status;
import com.brilliance.isc.swift.objmtconvert.annotation.TagName;
import com.brilliance.isc.swift.objmtconvert.annotation.model.MtCfg;
import com.brilliance.isc.swift.objmtconvert.model.AbsMTCreator;
import com.brilliance.isc.swift.objmtconvert.model.AbsMTValidator;
import com.brilliance.isc.swift.objmtconvert.model.commontag.ActnoBicAdrTagXXX;
import com.brilliance.isc.swift.objmtconvert.model.commontag.DcDateCurAmtTagXXX;
import com.brilliance.isc.swift.objmtconvert.model.commontag.TagResult;
import com.brilliance.isc.swift.objmtconvert.result.MtResult;
import com.brilliance.isc.swift.swifteditor.tag.TagFormat;
import com.brilliance.isc.swift.swifteditor.tag.TagLine;
import com.prowidesoftware.swift.model.Tag;
import com.prowidesoftware.swift.model.mt.AbstractMT;
import org.apache.commons.lang3.reflect.MethodUtils;
import org.apache.xmlbeans.impl.jam.mutable.MPackage;

import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.*;
import java.util.regex.Pattern;

/**
 * @author gechengyang
 * @date 2023/2/27
 */
public class MtValidatorUtil {


    private static final Map<String, TagLine> tagMap = TagFormat.TagMap;

    public static MtResult checkMTBusiness(AbsMTCreator absMTCreator, MtResult mtResult) {
        String msgType = absMTCreator.getMsgType();

        String clsName = "com.brilliance.isc.swift.objmtconvert.model.busvalidator.mt" + msgType.charAt(0) + "xx.MT" + msgType + "Validator";
        try {
            Class cls = Class.forName(clsName);
            Constructor constructor = cls.getConstructor(String.class, MtResult.class);
            AbsMTValidator absMTValidator = (AbsMTValidator) constructor.newInstance(absMTCreator.getAbstractMT().message(), mtResult);
            absMTValidator.bussinessValidator();
        } catch (Exception e) {
            e.printStackTrace();
            mtResult.setSuccess(false);
            mtResult.setContinueFlg(false);
//            mtResult.addDescription("加载【" + clsName + "】失败" + e.getMessage());
            mtResult.addDescription(Language.getLanguage("SYS_C1")+clsName+Language.getLanguage("SYS_C2") + e.getMessage());
            return mtResult;
        }
        //MethodUtils.invokeMethod()
        return mtResult;
    }
    public static void checkMTBusiness(MtResult mtResult) {
        //String msgType = mtResult.getAbstractMT().getMessageType();
        String msgType = MTUtil.getSwiftMtType(mtResult);
        String clsName = "com.brilliance.isc.swift.objmtconvert.model.busvalidator.mt" + msgType.charAt(0) + "xx.MT" + msgType + "Validator";
        try {
            Class cls = Class.forName(clsName);
            Constructor constructor = cls.getConstructor(String.class, MtResult.class);
            AbsMTValidator absMTValidator = (AbsMTValidator) constructor.newInstance(mtResult.getAbstractMT().message(), mtResult);
            absMTValidator.bussinessValidator();
        } catch (Exception e) {
            e.printStackTrace();
            mtResult.setSuccess(false);
            mtResult.setContinueFlg(false);
//            mtResult.addDescription("加载【" + clsName + "】失败" + e.getMessage());
            mtResult.addDescription(Language.getLanguage("SYS_C1")+clsName+Language.getLanguage("SYS_C2") +" "+ e.getMessage());
        }
        //MethodUtils.invokeMethod()
    }

    public static Field[] getFields(AbsMTCreator absMTCreator) {
        Class<?> clazz = absMTCreator.getClass();
        List<Field> fieldList = new ArrayList<>();
        Field[] field = clazz.getDeclaredFields();
        for (Field tempField : field) {
            fieldList.add(tempField);
        }
        while (true) {
            // System.out.println(field[0].getName());
            clazz = clazz.getSuperclass();
            if (clazz != null && clazz != Object.class) {
                field = clazz.getDeclaredFields();
                //System.out.println(field[0].getName());
                List<Field> l = Arrays.asList(field);
                for (Field tempField : l) {
                    fieldList.add(tempField);
                }
            } else {
                break;
            }
        }

        return fieldList.toArray(new Field[fieldList.size()]);
    }
    public static Field[] getFields(MtResult mtResult) {
        String msgType = MTUtil.getSwiftMtType(mtResult);
        String clsName = "com.brilliance.isc.swift.objmtconvert.model.mt" + msgType.charAt(0) + "xx.MT" + msgType + "Creator";
        Class<?> clazz = null;
        try {
            clazz = Class.forName(clsName);
            List<Field> fieldList = new ArrayList<>();
            Field[] field = clazz.getDeclaredFields();
            for (Field tempField : field) {
                fieldList.add(tempField);
            }
            while (true) {
                // System.out.println(field[0].getName());
                clazz = clazz.getSuperclass();
                if (clazz != null && clazz != Object.class) {
                    field = clazz.getDeclaredFields();
                    //System.out.println(field[0].getName());
                    List<Field> l = Arrays.asList(field);
                    for (Field tempField : l) {
                        fieldList.add(tempField);
                    }
                } else {
                    break;
                }
            }
            return fieldList.toArray(new Field[fieldList.size()]);
        } catch (Exception e) {
            e.printStackTrace();
            mtResult.setSuccess(false);
            mtResult.setContinueFlg(false);
//            mtResult.addDescription("加载【" + clsName + "】失败" + e.getMessage());
            mtResult.addDescription(Language.getLanguage("SYS_C1")+clsName+Language.getLanguage("SYS_C2") +" "+ e.getMessage());
        }
        return null;
    }
    public static Field[] getFields(MtResult mtResult,String msgType) {
        String clsName = "com.brilliance.isc.swift.objmtconvert.model.mt" + msgType.charAt(0) + "xx.mt"+msgType.charAt(0)+"XXAbsCreator.MT" + msgType + "AbsCreator";
        Class<?> clazz = null;
        try {
            clazz = Class.forName(clsName);
            List<Field> fieldList = new ArrayList<>();
            Field[] field = clazz.getDeclaredFields();
            for (Field tempField : field) {
                fieldList.add(tempField);
            }
            while (true) {
                // System.out.println(field[0].getName());
                clazz = clazz.getSuperclass();
                if (clazz != null && clazz != Object.class) {
                    field = clazz.getDeclaredFields();
                    //System.out.println(field[0].getName());
                    List<Field> l = Arrays.asList(field);
                    for (Field tempField : l) {
                        fieldList.add(tempField);
                    }
                } else {
                    break;
                }
            }
            return fieldList.toArray(new Field[fieldList.size()]);
        } catch (Exception e) {
            e.printStackTrace();
            mtResult.setSuccess(false);
            mtResult.setContinueFlg(false);
//            mtResult.addDescription("加载【" + clsName + "】失败" + e.getMessage());
            mtResult.addDescription(Language.getLanguage("SYS_C1")+clsName+Language.getLanguage("SYS_C2") +" "+ e.getMessage());
        }
        return null;
    }

    public static void checkMtMessage(MtResult mtResult){
        String reg = "";
        try {
            AbstractMT abstractMT = AbstractMT.parse(mtResult.getMessage());
            mtResult.setAbstractMT(abstractMT);
            String msgType = abstractMT.getMessageType();
            List<Tag> tags = abstractMT.getSwiftMessage().getBlock4().getTags();
            List<String> fieldMList = new ArrayList<>();
            Field[] f = getFields(mtResult);
            for (Field field : f) {
                TagName tagName = field.getAnnotation(TagName.class);
                Status status = field.getAnnotation(Status.class);
                if(field.getType().getTypeName().equals(List.class.getTypeName())&&status==null){
                    Field[] f2 = getFields(mtResult,msgType);
                    for (Field field2 : f2) {
                        tagName = field2.getAnnotation(TagName.class);
                        status = field2.getAnnotation(Status.class);
                        if(status!=null&&Constans.STATUS_MUST.equals(status.value())){
                            fieldMList.add(tagName.value()[0].substring(0,2));
                        }
                    }
                }else {
                    if(status!=null&&Constans.STATUS_MUST.equals(status.value())){
                        fieldMList.add(tagName.value()[0].substring(0,2));
                    }
                }
            }
            for (int i = 0; i < fieldMList.size(); i++) {
                boolean flag = true;
                for (Tag tag : tags) {
                    if(fieldMList.get(i).equals(tag.getName().substring(0,2))){
                        flag = false;
                    }
                }
                if(flag){
                    mtResult.setSuccess(false);
//                    String msg = String.format("SWIFT MT%s的%s域为M,值为空", msgType, fieldMList.get(i));
                    String msg = "";
                    if (MtCfg.LANGUAGE.equals("zh")){
                        msg = String.format(Language.getLanguage("SYS_C11")+"%s"+Language.getLanguage("SYS_C12")+"%s "+Language.getLanguage("SYS_C13"),  msgType, fieldMList.get(i));

                    }else{
                        msg = String.format(Language.getLanguage("SYS_C11")+"%s"+Language.getLanguage("SYS_C12")+"%s "+Language.getLanguage("SYS_C13"),  fieldMList.get(i) ,msgType);
                    }

                    mtResult.addDescription(msg);
                }
            }
            for (Tag tag : tags) {
                String tagName = tag.getName();
                String value = tag.getValue();
                if(tagMap.get(tagName) == null){
                    continue;
                }
                reg = tagMap.get(tagName).toAnalyzeReg();
                TagLine tagLine = tagMap.get(tagName);
                String[] lines = new String[]{value};
                if(tagLine.cellList.size() == 1 && tagLine.cellList.get(0).line > 50){
                    //行数超标后，线程会卡死
                    reg = tagMap.get(tagName).cellList.get(0).toReg(false,true);
                    lines = value.split("\\r?\\n");
                }
                for (String line : lines) {
                    if (!Pattern.matches(reg, line)) {
                        String pattern = tagMap.get(tagName).getPattern();
                        mtResult.setSuccess(false);
    //                        String msg = String.format("【tag的元素校验】SWIFT MT%s的%s域,值为%s正确的格式为%s", msgType,tagName,Constans.NEW_LINE+value+Constans.NEW_LINE,pattern);
                        String msg = "";
                        if (MtCfg.LANGUAGE.equals("zh")){
                            msg = String.format(Language.getLanguage("SYS_C3")+"SWIFT MT%s"+Language.getLanguage("SYS_C4")+
                                            "%s"+Language.getLanguage("SYS_C5")+"%s"+Language.getLanguage("SYS_C6")+"%s",
                                    msgType,tagName,Constans.NEW_LINE+value+Constans.NEW_LINE,pattern);
                        }else{
                            msg = String.format(Language.getLanguage("SYS_C3")+" %s "+Language.getLanguage("SYS_C4")+
                                            " SWIFT MT%s "+Language.getLanguage("SYS_C5")+" %s"+Language.getLanguage("SYS_C6")+" %s ",
                                    tagName,msgType,Constans.NEW_LINE+value+Constans.NEW_LINE,pattern);
                        }
                        mtResult.addDescription(msg);
                        break;
                    }
                }

            }
        } catch (IOException e) {
            e.printStackTrace();
            mtResult.addDescription(e.getMessage());
            mtResult.setSuccess(false);
        }
    }

    public static MtResult checkMTTags(AbsMTCreator absMTCreator, MtResult mtResult) {
        if (!mtResult.isContinueFlg())
            return mtResult;
        String clsName = absMTCreator.getClass().getName();
        // Field[] f = absMTCreator.getClass().getFields();
        Field[] f = getFields(absMTCreator);

        if (0 == f.length) {
//            mtResult.addDescription(clsName + "的属性都无注解");+
            mtResult.addDescription(clsName + Language.getLanguage("SYS_C7"));
            mtResult.setSuccess(false);
            mtResult.setContinueFlg(false);
            mtResult.setMsgType(absMTCreator.getMsgType());
            return mtResult;
        } else {
            // 校验
            for (Field field : f) {
                try {
                    //TagName tagName = field.getAnnotation(TagName.class);
                    Status status = field.getAnnotation(Status.class);
                    String fieldName = field.getName();
                    if ("mtResult".equals(fieldName)) {
                        continue;
                    }
                    String methodName = "get" + String.valueOf(fieldName.charAt(0)).toUpperCase() + fieldName.substring(1);
                    Object object = MethodUtils.invokeMethod(absMTCreator, methodName);
                    if (status != null && Constans.STATUS_MUST.equals(status.value()) && Objects.isNull(object)) {
                        mtResult.setSuccess(false);
                        mtResult.setContinueFlg(false);
//                        mtResult.addDescription("请检查类【" + clsName + "】的属性【" + fieldName + "】是否赋值");
                        if (MtCfg.LANGUAGE.equals("zh")){
                            mtResult.addDescription(Language.getLanguage("SYS_C8") + clsName + Language.getLanguage("SYS_C9") + fieldName + Language.getLanguage("SYS_C10"));
                        }else{//"请检查类【" + clsName + "】的属性【" + fieldName + "】是否赋值
                            mtResult.addDescription(Language.getLanguage("SYS_C8") + fieldName + Language.getLanguage("SYS_C9") + clsName + Language.getLanguage("SYS_C10"));
                        }
//                        mtResult.addDescription("请检查类【" + clsName + "】的属性【" + fieldName + "】是否赋值");
                        // return mtResult;
                    }


                    //处理数组属性
                    if (object instanceof List) {
                        List<Object> list = (List<Object>) object;
                        for (Object subObj : list) {
                            commonValidator(absMTCreator, subObj, mtResult, field);
                        }
                    } else {
                        commonValidator(absMTCreator, object, mtResult, field);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    mtResult.addDescription(e.getMessage());
                    mtResult.setSuccess(false);
                    return mtResult;
                }
            }
        }
//        if(StringUtils.isNotEmpty(sb.toString())){
//            mtResult.setMessage(sb.toString());
//        }
        return mtResult;
    }

    public static void commonValidator(AbsMTCreator absMTCreator, Object object, MtResult mtResult, Field field) {
        String[] tagN = null;
        String tag = "";
        String value = "";
        String reg = "";
        String statusStr = "";
        //String tagname="";
        String value_spilt = "";
        Map<String, Object> map = null;
        Map<String, Object> tagValueMap = null;
        boolean flag = false;
        String content = "";
        TagName tagName = field.getAnnotation(TagName.class);
        if ("20".equals(tagName))
            System.out.println(111);
        if (tagName != null) {
            tagN = tagName.value();
        }

        Status status = field.getAnnotation(Status.class);
        String fieldName = field.getName();

        if (tagN != null && object instanceof String) {
            tag = tagN[0];
            value = (String) object;
            reg = tagMap.get(tag).toAnalyzeReg();

        } else if (object instanceof BigDecimal) {
            Assert.notNull(tagN);
            tag = tagN[0];
            BigDecimal bigDecimal = (BigDecimal) object;
            value= changeSymbol(bigDecimal);
            reg = tagMap.get(tag).toAnalyzeReg();
        } else if (object instanceof ActnoBicAdrTagXXX) {
            ActnoBicAdrTagXXX actnoBicAdrTagXXX = (ActnoBicAdrTagXXX) object;
            TagResult tagResult = actnoBicAdrTagXXX.getTagResult();
            if (tagResult != null) {
                tag = tagResult.getTagBefore() + tagResult.getTagEnd();
                value = tagResult.getValue();
                reg = tagMap.get(tag).toAnalyzeReg();
                map = tagMap.get(tag).toSegRegMap();
                tagValueMap = tagResult.getTagValueMap();
                flag = true;
            }
        } else if (object instanceof DcDateCurAmtTagXXX) {
            DcDateCurAmtTagXXX dcDateCurAmtTagXXX = (DcDateCurAmtTagXXX) object;
            TagResult tagResult = dcDateCurAmtTagXXX.getTagResult();
            if (tagResult != null) {
                tag = tagResult.getTagBefore() + tagResult.getTagEnd();
                value = tagResult.getValue();
                reg = tagMap.get(tag).toAnalyzeReg();
                map = tagMap.get(tag).toSegRegMap();
                tagValueMap = tagResult.getTagValueMap();
                flag = true;
            }
        } else if (object instanceof AbsMTCreator) {
            AbsMTCreator subAbsMtCreator = (AbsMTCreator) object;
            subAbsMtCreator.setMsgType(absMTCreator.getMsgType());
            checkMTTags(subAbsMtCreator, mtResult);
        }

        if (status != null) {
            statusStr = status.value();
            if (statusStr.equals(Constans.STATUS_MUST) && value.equals("")) {
                mtResult.setSuccess(false);
//                String msg = String.format("SWIFT MT%s的%s所在域为M,值为空", absMTCreator.getMsgType(), fieldName);
                String msg = "";
                if (MtCfg.LANGUAGE.equals("zh")){
                    msg = String.format(Language.getLanguage("SYS_C11")+"%s"+Language.getLanguage("SYS_C12")+"%s"+Language.getLanguage("SYS_C13"), absMTCreator.getMsgType(), fieldName);
                }else{
                    msg = String.format(Language.getLanguage("SYS_C11")+"%s"+Language.getLanguage("SYS_C12")+"%s"+Language.getLanguage("SYS_C13"), fieldName, absMTCreator.getMsgType());
                }
                mtResult.addDescription(msg);
            }
        }
//        if (flag) {
//            for (String s : tagValueMap.keySet()) {
//                for (String s1 : map.keySet()) {
//                    Map map1 = (Map<String, Object>) map.get(s1);
//                    if (s.equals(map1.get("area")) || map1.size() == 1) {
//                        String regex = "(" + map1.get("reg") + ")";
//                        if (!Pattern.matches(regex, String.valueOf(tagValueMap.get(s)))) {
//                            mtResult.setSuccess(false);
//                            String msg = String.format("【tag的子元素校验】SWIFT MT%s的属性%s【%s,%s字段】值为%s,正确正则表达式为%s", absMTCreator.getMsgType(), fieldName, tag, s, tagValueMap.get(s), regex);
//                            mtResult.addDescription(msg);
//                        }
//                    }
//                }
//            }
//        } else {
        if (!Pattern.matches(reg, value)) {
            String pattern = tagMap.get(tag).getPattern();
            mtResult.setSuccess(false);
            // String msg = String.format("SWIFT MT%s的%s值%s不对,正确正则表达式为%s", absMTCreator.getMsgType(), fieldName, value, reg);
//            String msg = String.format("【tag的元素校验】SWIFT MT%s的属性%s【%s,%s字段】值为%s,正确的格式为%s", absMTCreator.getMsgType(), fieldName, tag, fieldName, value, pattern);
            String msg = "";
            if (MtCfg.LANGUAGE.equals("zh")){
                msg = String.format(Language.getLanguage("SYS_C14")+"%s"+Language.getLanguage("SYS_C15")+"%s"+Language.getLanguage("SYS_C16")+"%s"+Language.getLanguage("SYS_C17")+"%s"+Language.getLanguage("SYS_C18")+"%s"+Language.getLanguage("SYS_C19"), absMTCreator.getMsgType(), fieldName, tag, fieldName, value, pattern);
            }else{
                msg = String.format(Language.getLanguage("SYS_C14")+"%s"+Language.getLanguage("SYS_C15")+"%s"+Language.getLanguage("SYS_C16")+"%s"+Language.getLanguage("SYS_C17")+"%s"+Language.getLanguage("SYS_C18")+"%s"+Language.getLanguage("SYS_C19"), fieldName, tag, absMTCreator.getMsgType(), fieldName, value, pattern);
            }
            mtResult.addDescription(msg);
        }
//        }
    }

    public static String changeSymbol(BigDecimal bigDecimal) {
        String decimalStr = bigDecimal.toPlainString();
        if (decimalStr.contains(".")) {
            decimalStr = decimalStr.replaceAll("\\.", ",");
        }
        else
        {
            decimalStr=decimalStr+",";
        }
        return decimalStr;
    }
}
