package org.example.Utils;

import org.example.Entity.System.LoginUserInfo;
import org.example.Enums.SystemTypeEnums;

import java.util.*;
import java.util.regex.*;
import java.text.SimpleDateFormat;
import java.util.function.Function;
import java.util.function.Predicate;


class Analyzer {
    String sourcestr;
    String analyerstr;
    private SystemTypeEnums.PmType pmtype = SystemTypeEnums.PmType.sql;

    // 正则表达式定义，注意Java的转义字符处理
    private static final Pattern noDotPmReg = Pattern.compile("\\[([%|_|,]){0,}([\\{])([^'|\\{|\\}|&|=|>|\\<| |\\[|\\]])+([\\}])([%|_|,]){0,}\\]", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
    private static final Pattern DotPmReg = Pattern.compile("'([%|_|,]){0,}([\\{])([^'|\\{|\\}|&|=|>|\\<| ])+([\\}])([%|_|,]){0,}'", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
    private static final Pattern leftPmReg = Pattern.compile("\\{([^'\\{\\}&=<> ,])+([\\}]?)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
    private static final Pattern rightPmReg = Pattern.compile("([\\{]?)([^'\\{\\}&=<> ,])+}", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);

    List<String> pms = null;
    List<String> dotPms = null;
    public List<String> noDotPms = null;
    public Map<String, String> pmDicts = new HashMap<>();
    public List<String> ignorePms = new ArrayList<>();

    public Analyzer(String analyestr) {
        this.sourcestr = analyestr;
        this.analyerstr = this.sourcestr;
    }

    public Analyzer(String analyestr, SystemTypeEnums.PmType pmtype) {
        this(analyestr);
        this.pmtype = pmtype;
    }

    public List<String> getPms() {
        if (pms == null) {
            pms = new ArrayList<>();
            if (sourcestr == null || sourcestr.isEmpty()) {
                return pms;
            }
            if (sourcestr.indexOf("{") < 0 && sourcestr.indexOf("}") < 0) {
                return pms;
            }

            dotPms = new ArrayList<>();
            noDotPms = new ArrayList<>();

            Pattern[] regs = {noDotPmReg, DotPmReg, leftPmReg, rightPmReg};

            for (Pattern reg : regs) {
                Matcher matcher = reg.matcher(analyerstr);
                while (matcher.find()) {
                    String pm = matcher.group().replace("|", "\\|");

                    if (pmDicts.containsKey(pm)) {
                        continue;
                    }
                    pmDicts.put(pm, "1");

                    if (pm.indexOf("{") < 0 && pm.indexOf("}") < 0) {
                        continue;
                    }

                    // 处理trim特殊字符（C#的Trim等效实现）
                    String trimmedPm = pm.replaceAll("^[%_,'#]+", "").replaceAll("[%_,'#]+$", "");
                    String item = trimmedPm.replace("{", "")
                            .replace("}", "")
                            .replace("[", "")
                            .replace("]", "")
                            .toLowerCase();

                    // 跳过数字参数（假设Web.Core.Util.RegexUtil.NumberReg是数字正则）
                    if (item.matches("^[0-9]+$")) {
                        continue;
                    }

                    if (!pms.contains(item)) {
                        pms.add(item);
                    }

                    // 处理双括号参数忽略
                    if (analyerstr.indexOf("{{" + pm + "}}") > -1) {
                        ignorePms.add(item);
                    }

                    boolean noPm = pm.startsWith("[") && pm.endsWith("]");

                    if (!noPm) {
                        if (pm.startsWith("'")) {
                            if (!dotPms.contains(item)) {
                                dotPms.add(item);
                            }
                        } else {
                            if (!sourcestr.equals(pm) && !dotPms.contains(item)
                                    && !noDotPms.contains(item) && pmtype != SystemTypeEnums.PmType.program
                                    && pmtype != SystemTypeEnums.PmType.ignorenull) {
                                noDotPms.add(item);
                            }
                        }
                    }

                    int pmI = pms.indexOf(item);
                    String rmcVal = String.format("{%d}", pmI);

                    // 替换pm中的trim部分为rmcVal
                    String replacedPm = pm.replace(trimmedPm, rmcVal)
                            .replaceAll("^'", "")
                            .replaceAll("'$", "");
                    rmcVal = String.format(dotPms.contains(item) ? "'%s'" : "%s", replacedPm);

                    if (noPm) {
                        analyerstr = analyerstr.replace(pm, rmcVal);
                    } else {
                        // 转义正则特殊字符后再编译
                        String escapedPm = Pattern.quote(pm);
                        analyerstr = Pattern.compile(escapedPm, Pattern.CASE_INSENSITIVE)
                                .matcher(analyerstr)
                                .replaceAll(rmcVal);
                    }
                }
            }
        }
        return pms;
    }

    // 判断字符串是否为数字
    private boolean isNumber(String str) {
        if (str == null || str.isEmpty()) return false;
        return str.matches("^[+-]?\\d+(\\.\\d+)?$");
    }
}

public class PmAnalyzer {
    private String sourcestr;
    private LoginUserInfo user;
    private SystemTypeEnums.PmType pmtype = SystemTypeEnums.PmType.sql;
    private static final Pattern NDReg = Pattern.compile("[^\\d\\.\\-]");
    private static final List<Analyzer> analyzers = new ArrayList<>();
    private Analyzer analyzer;

    public PmAnalyzer(LoginUserInfo user, String analyestr) {
        this.user = user;
        this.sourcestr = (analyestr == null) ? "" : analyestr;
    }

    public PmAnalyzer(LoginUserInfo user, String analyestr, SystemTypeEnums.PmType pmtype) {
        this(user, analyestr);
        this.pmtype = pmtype;
    }

    private Analyzer getAnalyzer() {
        if (analyzer == null) {
            // 简化处理，不使用缓存逻辑
            analyzer = new Analyzer(sourcestr, pmtype);
        }
        return analyzer;
    }

    public List<String> getPms() {
        return getAnalyzer().getPms();
    }

    public List<String> getIgnorePms() {
        return getAnalyzer().ignorePms;
    }

    public LoginUserInfo getUser() {
        if (user == null) {
            user = new LoginUserInfo();
        }
        return user;
    }

    public void setUser(LoginUserInfo user) {
        this.user = user;
    }

    private boolean containsKey(String pm, Map<String, Object> row, Map<String, Object> leftRow) {
        if (pm.contains("parent.")) {
            String key = pm.split("\\.")[1];
            return leftRow != null && leftRow.containsKey(key);
        }
        return row != null && row.containsKey(pm);
    }

    private String dealVal(Object val) {
        if (val == null) return "";
        if (val instanceof Date) {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            return sdf.format((Date) val);
        }
        return val.toString();
    }

    public String FillPms(Map<String, Object> row, Map<String, Object> leftRow, SystemTypeEnums.PmType pmtype) {
        return fillpms(pm -> {
            String val = "";
            if (containsKey(pm, row, leftRow)) {
                if (pm.contains("parent.")) {
                    String key = pm.split("\\.")[1];
                    val = dealVal(leftRow.get(key));
                } else {
                    val = row == null ? "" : dealVal(row.get(pm));
                }
            }
            if (val.contains(",")) {
                Pattern inReg = Pattern.compile("\\ +in\\ ?\\('\\{" + pm + "\\}'", Pattern.CASE_INSENSITIVE);
                if (inReg.matcher(sourcestr).find()) {
                    val = val.replace(",", "','");
                    return val;
                }
            }

            val = val.replace("''", "'").replace("'", "''");
//            val = val.replace("''", "'");
            if (getAnalyzer().noDotPms.contains(pm)) {
                if (val.isEmpty() || NDReg.matcher(val).find()) {
                    return String.format("'%s'", val);
                }
            }
            return val;
        }, pm -> containsKey(pm, row, leftRow), pmtype);
    }

    public String FillPms(Map<String, Object> row, Map<String, Object> leftRow) {
        return FillPms(row, leftRow, this.pmtype);
    }

    private String fillpms(Function<String, String> getval, Predicate<String> containskey, SystemTypeEnums.PmType pmtype) {
        List<String> pms = getPms();
//        System.out.println("fillpms " + pms);
        if (pms == null || pms.isEmpty()) {
            return sourcestr;
        }

//        System.out.println("fillpms " + pms + "user: " + getUser().UserName);
        // 创建参数映射，用于替换
        Map<Integer, String> indexValues = new HashMap<>();
        for (int i = 0; i < pms.size(); i++) {
            String pm = pms.get(i).replace("\\|", "|");
            String val = "";
            String valOrig = "";

            if (!containskey.test(pm) && (pmtype == SystemTypeEnums.PmType.ignorenull || (getIgnorePms() != null && getIgnorePms().contains(pm)))) {
                val = String.format("{%s}", pm);
            } else {
                valOrig = val = getval.apply(pm);
            }
            // 处理用户信息相关参数
            if (valOrig.isEmpty() || "''".equals(valOrig)) {
                switch (pm) {
                    case "loginid":
                        val = getUser().UserId;  // 注意使用getter方法
                        break;
                    case "lginname":
                    case "loginname":
                        val = getUser().UserName;  // 注意使用getter方法
                        break;
                    case "loginaccount":
                        val = getUser().UserCode;  // 注意使用getter方法
                        break;
                    case "logintype":
                        val = getUser().LoginType == null ? "" : getUser().LoginType + "";  // 注意使用getter方法
                        break;
                    case "seriesid":
                        val = getUser().SeriesId;  // 注意使用getter方法
                        break;
                    case "server":
                    case "serverid":
                        val = getUser().SeriesId;  // 注意使用getter方法
                        break;
                    case "pwd":
                        val = getUser().Pwd;  // 注意使用getter方法
                        break;
                    case "password":
                        val = getUser().Pwd;  // 注意使用getter方法
                        break;
                    case "clientid":
                    case "loginclientid":
                        val = getUser().ClientId == null ? "" : getUser().ClientId + "";  // 注意使用getter方法
                        break;
                }

                // 处理其他用户信息
                Map<String, Object> other = getUser().Other;  // 注意使用getter方法
                if (other != null && other.containsKey(pm)) {
                    Object otherVal = other.get(pm);
                    if (otherVal instanceof Hashtable) {
                        Hashtable<?, ?> hashVal = (Hashtable<?, ?>) otherVal;
                        if (hashVal.containsKey("value")) {
                            val = hashVal.get("value").toString();
                        } else {
                            val = otherVal.toString();
                        }
                    } else {
                        val = otherVal.toString();
                    }
                }
            }

            // 将参数和对应的值存入映射
            indexValues.put(i, val); // 用索引作为键
        }
//        System.out.println("fillpms+foratStr ");
        try {
            String formatStr = getAnalyzer().analyerstr.replace("{{", "{").replace("}}", "}");
            // 按索引替换占位符 {0}, {1}, ...
//            System.out.println("fillpms+formatStr " + formatStr + indexValues.toString());
            for (Map.Entry<Integer, String> entry : indexValues.entrySet()) {
                String placeholder = "{" + entry.getKey() + "}";
                String value = entry.getValue();
                formatStr = formatStr.replace(placeholder, value);
            }
//            System.out.println("fillpms+formatStr " + formatStr);
            return formatStr;
        } catch (Exception e) {
            String tipStr = "请检查配置是否正确，字段配置值：【" + sourcestr + "】，处理后：【" + getAnalyzer().analyerstr + "】。";
            throw new RuntimeException(tipStr + e.getMessage(), e);
        }
    }
}
