package com.brilliance.isc.doc.convert;

import com.brilliance.mda.runtime.mda.config.IniConfig;
import com.brilliance.isc.bo.Bnl;
import com.brilliance.isc.bo.Smh;
import com.brilliance.isc.common.doc.TextResultVo;
import com.brilliance.isc.mda.dao.BnlMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import java.io.ByteArrayInputStream;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 针对老国结电证面函转换支持服务
 */
@Slf4j
@Component
public class OldElcDocConvertService {
    static Pattern pattern = Pattern.compile("^:MT:.*?:([^:]+)$");
    @Autowired
    private BnlMapper bnlMapper;
    @Autowired
    private IniConfig elcComIni;
    @Autowired
    private IniConfig elcTagAdvIni;

    public boolean isOldElc(Smh smh) {
        return smh.getInr().length() == 8 && "txt".equalsIgnoreCase(smh.getDocfxt()) && "ELC".equalsIgnoreCase(smh.getCortyp());
    }

    public TextResultVo showElc(byte[] dataBytes, Smh smh) throws Exception {
        TextResultVo textResultVo = new TextResultVo();
        Map<String, Object> rtnMap = new LinkedHashMap<>();
        List<String> lines = IOUtils.readLines(new ByteArrayInputStream(dataBytes), "GBK");
        String msgtyp = fetchMsgtyp(lines, smh);
        if (log.isInfoEnabled()) {
            log.info("准备尝试展示老国结的电证报文,msgtyp={}", msgtyp);
        }
        Assert.hasText(msgtyp, "无法识别老国结电证报文类型");
        String[] field = new String[4];
        StringBuilder part4 = null;
        for (String line : lines) {
            if (line.startsWith(":")) {
                //新的字段
                if (part4 != null) {
                    //开始处理
                    field[3] = part4.toString();
                    //描述加工
                    String eTag = convertTag(field[0], msgtyp);
                    //值加工和最终封装该字段
                    packMsg(field, eTag, rtnMap);
                    part4 = null;
                    Arrays.fill(field, null);
                }
                field = line.substring(1).split(":", 4);
                if (noShow(field[0])) {
                    continue;
                }
                if (part4 == null) {
                    part4 = new StringBuilder();
                }
                part4.append(field[3].trim());
            } else {
                part4.append("\n").append(line.trim());
            }
        }
        if (part4 != null) {
            field[3] = part4.toString();
            //描述加工
            String eTag = convertTag(field[0], msgtyp);
            //值加工和最终封装该字段
            packMsg(field, eTag, rtnMap);
        }
        textResultVo.setFormatData(rtnMap);
        textResultVo.setData(new String(dataBytes, "GBK"));
        return textResultVo;
    }

    private String fetchMsgtyp(List<String> rawMsg, Smh smh) {
        for (String line : rawMsg) {
            Matcher matcher = pattern.matcher(line);
            if (matcher.find()) {
                return matcher.group(1);
            }
        }
        return smh.getMsgtyp();
    }

    private boolean noShow(String tag) {
        return "".equals(elcComIni.get("NOSHOW-TAG", tag));
    }

    private String convertTag(String tag, String msgTyp) {
        String cTag = elcTagAdvIni.get(msgTyp, tag);
        if (StringUtils.hasText(cTag)) {
            return cTag;
        }
        cTag = elcComIni.get("SWIFT-FIOTAG", tag);
        return getOrDefault(cTag, tag);
    }

    private void packMsg(String[] field, String eTag, Map<String, Object> rtnMap) {
        String eVal = null;
        String tag = field[0];
        String val = field[3];
        //判断是不是报文类型字段
        if ("MT".equalsIgnoreCase(tag)) {
            Map<String, Object> itemMap = new HashMap<>();
            itemMap.put("value", val);
            itemMap.put("kind", "0");
            itemMap.put("label", "MesgType");
            rtnMap.put("MesgType", itemMap);
        }
        //判断是不是机构类的
        else if (eTag.endsWith("机构") || eTag.endsWith("行号")) {
            String bnkNo = val;
            Bnl bnl = bnlMapper.selectByFqcyjg(bnkNo);
            if (bnl != null) {
                String bnkName = bnl.getFukrhm();
                eVal = val + " :" + bnkName;
            } else if ("0000".equals(val)) {
                eVal = val + " :国家处理中心";
            }
            packItem(eTag, getOrDefault(eVal, val), "2", field, rtnMap);
        }
        //判断值在不在elcsup.ini配置里面需要转换
        else if (elcComIni.getBlock(tag + "CODNAM") != null) {
            eVal = elcComIni.get(tag + "CODNAM", val);
            packItem(eTag, getOrDefault(eVal, val), "2", field, rtnMap);
        } else {
            //上述都不满足，直接原值返回
            packItem(eTag, val, "2", field, rtnMap);
        }
    }

    private void packItem(String eTag, String eVal, String kind, String[] field, Map<String, Object> rtnMap) {
        Map<String, Object> itemMap = new HashMap<>();
        itemMap.put("value", eVal);
        itemMap.put("kind", kind);
        itemMap.put("label", eTag);
        rtnMap.put(field[0] + field[1] + field[2], itemMap);
    }

    private String getOrDefault(String real, String def) {
        return StringUtils.hasText(real) ? real : def;
    }
}
