package org.example.Utils;

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

import static org.example.Utils.NativeExtensionUtils.Trim;

public class SqlAnalyzer {
    private String cmdText;
    private String mainPart;
    private String allMainPart;
    private String orderBy;
    private String groupBy;
    private String having;
    public String OldWhere;
    private String fromPart;
    public String QueryPart;
    public ArrayList<String> InnerPms;
    private HashMap<String, String> dotPms;
    private ArrayList<String> dotPmNames;
    public ArrayList<String> AliasPms;

    private int sIndex;
    private int withIndex;
    private int tIndex;
    private int fIndex;
    private boolean _isUnion;
    private boolean analyzedPms = false;

    // 预编译正则表达式（对应C#的静态Regex）
    // 修复后的正则表达式：限制后行断言中的数字位数
    private static final Pattern QUERY_PART_REG = Pattern.compile("(?is)(?<=select\\ ).*?(?=from)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
    private static final Pattern TOP_QUERY_PART_REG = Pattern.compile("(?is)(?<=top (\\d){1,10} ).*?(?=from)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
    private static final Pattern UNION_QUERY_PART_REG = Pattern.compile("(?is)(?<=select\\ ).*?(?=union)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
    private static final Pattern FROM_PART_REG = Pattern.compile("(?is)(?<=from\\ )[^)]+(?= |\\))", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
    private static final Pattern SEL_X_FROM_REG = Pattern.compile("select( ){1,}\\*( ){1,}from( ){0,}(\\r\\n){0,}\\(+", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);

    public SqlAnalyzer(String source) {
        this.cmdText = source;
        String cmdTextLower = Trim(source).toLowerCase();
        this._isSelect = !cmdTextLower.contains("exec ");

        // 初始化成员变量
        this.mainPart = "";
        this.allMainPart = "";
        this.orderBy = "";
        this.groupBy = "";
        this.having = "";
        this.OldWhere = "";
        this.fromPart = "";
        this.QueryPart = "";
        this.InnerPms = new ArrayList<>();
        this.dotPms = new HashMap<>();
        this.dotPmNames = new ArrayList<>();
        this.AliasPms = new ArrayList<>();

        this.doAnalyze();
    }


    // Getter方法（对应C\#的属性）
    private Boolean _isSelect;

    public Boolean isIsSelectString() {
        return _isSelect;
    }

    private String _cmdText;

    public String getCmdText() {
        return cmdText;
    }

    public String getMainPart() {
        return mainPart;
    }

    public String getAllMainPart() {
        return allMainPart;
    }

    public String getOrderBy() {
        return orderBy;
    }

    public String getGroupBy() {
        return groupBy;
    }

    public String getHaving() {
        return having;
    }

    public String getOldWhere() {
        return OldWhere;
    }

    public String getFromPart() {
        return fromPart;
    }

    public String getQueryPart() {
        return QueryPart;
    }

    public ArrayList<String> getInnerPms() {
        return InnerPms;
    }

    public HashMap<String, String> getDotPms() {
        return dotPms;
    }

    public ArrayList<String> getDotPmNames() {
        return dotPmNames;
    }

    public ArrayList<String> getAliasPms() {
        return AliasPms;
    }


    /**
     * 核心分析方法：清理SQL并解析结构
     */
    private void doAnalyze() {
        if (cmdText == null || cmdText.isEmpty() || !_isSelect) {
            mainPart = cmdText;
            return;
        }

        String cmdText = this.cmdText;

        // 清理SQL：去除注释、多余空格、换行等
        cmdText = Pattern.compile("ORDER\\ +BY", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE).matcher(cmdText).replaceAll("order by");
        cmdText = Pattern.compile("/\\*[^/\\*]+\\*/", Pattern.MULTILINE).matcher(cmdText).replaceAll(""); // 去除/* */注释
        cmdText = Pattern.compile("--[^\\r\\n].*\\r\\n", Pattern.MULTILINE).matcher(cmdText).replaceAll("\r\n"); // 去除--注释
        cmdText = Pattern.compile("\\r\\n", Pattern.MULTILINE).matcher(cmdText).replaceAll(" "); // 换行转空格
        cmdText = Pattern.compile("\\r", Pattern.MULTILINE).matcher(cmdText).replaceAll(" ");
        cmdText = Pattern.compile("\\ +", Pattern.MULTILINE).matcher(cmdText).replaceAll(" "); // 多个空格合并
        cmdText = Pattern.compile("\\t+", Pattern.MULTILINE).matcher(cmdText).replaceAll(" "); // 制表符转空格
        cmdText = Pattern.compile(",\\ ", Pattern.MULTILINE).matcher(cmdText).replaceAll(","); // 逗号后空格清理
        cmdText = Pattern.compile("\\ ,", Pattern.MULTILINE).matcher(cmdText).replaceAll(","); // 逗号前空格清理
        cmdText = Pattern.compile("( |\\r\\n)*\\,( |\\r\\n)*", Pattern.MULTILINE).matcher(cmdText).replaceAll(",").trim();

        this.cmdText = cmdText;

        // 解析SQL各部分
        doAnalyzePart();

        // 计算关键索引（WITH/SELECT/FROM）
        withIndex = getRegIndex(cmdText, "with");
        sIndex = getRegIndex(cmdText, withIndex >= 0 ? "\\)\\ +select" : "select", false, 0);
        fIndex = getRegIndex(cmdText, "from", false, sIndex);

        // 提取查询字段部分（QueryPart）和FROM部分（FromPart）
        Matcher m;
        if ((m = QUERY_PART_REG.matcher(mainPart)).find() || (m = UNION_QUERY_PART_REG.matcher(mainPart)).find()) {
            QueryPart = m.group();
        }
        if ((m = TOP_QUERY_PART_REG.matcher(mainPart)).find()) {
            QueryPart = m.group();
        }
        if ((m = FROM_PART_REG.matcher(mainPart)).find()) {
            fromPart = m.group();
        }
    }


    /**
     * 查找正则匹配的索引位置
     *
     * @param source     源字符串
     * @param regText    正则表达式
     * @param last       是否取最后一个匹配
     * @param startIndex 起始查找位置
     * @return 匹配的索引（-1表示未找到）
     */
    private int getRegIndex(String source, String regText, boolean last, int startIndex) {
        if (source == null || source.isEmpty() || regText == null || regText.isEmpty()) {
            return -1;
        }

        Pattern pattern = Pattern.compile("( |\\r\\n|\\()+" + regText + "( |\\r\\n|\\()", Pattern.CASE_INSENSITIVE);
        Matcher matcher = pattern.matcher(" " + source); // 前缀加空格避免边界问题

        List<Integer> indices = new ArrayList<>();
        while (matcher.find()) {
            int index = matcher.start();
            if (index >= startIndex) {
                indices.add(index);
            }
        }

        if (indices.isEmpty()) {
            return -1;
        }

        return last ? indices.get(indices.size() - 1) : indices.get(0);
    }

    // 简化调用：默认不取最后，起始位置0
    private int getRegIndex(String source, String regText) {
        return getRegIndex(source, regText, false, 0);
    }

    private int getRegIndex(String source, String regText, boolean last) {
        return getRegIndex(source, regText, last, 0);
    }


    /**
     * 处理SQL中的括号（替换括号内内容为占位符，避免解析干扰）
     */
    private String dealCmdStr() {
        Pattern reg = Pattern.compile("\\(([^\\(|\\)]*)\\)");
        String cmd = cmdText;
        Matcher matcher = reg.matcher(cmd);

        while (matcher.find()) {
            String val = matcher.group();
            // 用同等长度的"1"替换括号内内容（保持索引位置大致准确）
            StringBuilder replacement = new StringBuilder();
            for (int i = 0; i < val.length(); i++) {
                replacement.append("1");
            }
            cmd = cmd.replace(val, replacement.toString());
        }
        return cmd;
    }


    /**
     * 解析SQL的GROUP BY/ORDER BY/WHERE等部分
     */
    private void doAnalyzePart() {
        String cmd = dealCmdStr();

        // 计算各关键字的索引
        int oIndex = getRegIndex(cmd, "order by", true, 0); // ORDER BY索引
        int gIndex = getRegIndex(cmd, "group by", true, 0); // GROUP BY索引
        int uIndex = getRegIndex(cmd, "union", false, 0); // UNION索引
        int jIndex = getRegIndex(cmd, "join", true, 0); // JOIN索引
        int hIndex = getRegIndex(cmd, "having", true, 0); // HAVING索引
        int kIndex = getRegIndex(cmd, "on", true, 0); // ON索引
        int khIndex = getRegIndex(cmd, "\\)", false, uIndex); // 右括号索引
        int wIndex = getRegIndex(cmd, "where", true, 0); // WHERE索引
        tIndex = getRegIndex(cmd, "select top", true, 0); // SELECT TOP索引

        // 处理UNION查询
        if (uIndex > 0 && uIndex > kIndex && uIndex > wIndex && !(khIndex > 0 && wIndex > khIndex)) {
            doAnalyzeUnion();
            return;
        }

        // 解析GROUP BY和HAVING
        if (gIndex > kIndex && gIndex > wIndex) {
            groupBy = cmdText.substring(gIndex);
            if (oIndex > gIndex) {
                groupBy = cmdText.substring(gIndex, oIndex);
            }
            if (hIndex > gIndex) {
                groupBy = cmdText.substring(gIndex, hIndex);
                having = (oIndex > hIndex) ? cmdText.substring(hIndex, oIndex) : cmdText.substring(hIndex);
            }
        }

        // 解析ORDER BY
        if (oIndex > kIndex && oIndex > wIndex) {
            orderBy = cmdText.substring(oIndex);
        }

        // 解析WHERE条件
        if (wIndex > 0 && wIndex > kIndex) {
            OldWhere = cmdText.substring(wIndex);
            if (oIndex > 0 && oIndex > wIndex) {
                OldWhere = cmdText.substring(wIndex, oIndex);
            }
            if (gIndex > 0 && gIndex > wIndex) {
                OldWhere = cmdText.substring(wIndex, gIndex);
            }

            int mpIndex = wIndex;
            mainPart = cmdText.substring(0, mpIndex);

            // 处理嵌套WHERE的情况
            if (mpIndex < wIndex) {
                int innerWIndex = getRegIndex(mainPart, "where", true, 0);
                if (innerWIndex > 0 && innerWIndex > kIndex) {
                    if (oIndex > 0 && oIndex > innerWIndex) {
                        OldWhere = mainPart.substring(innerWIndex, oIndex);
                    }
                    if (gIndex > 0 && gIndex > innerWIndex) {
                        OldWhere = mainPart.substring(innerWIndex, gIndex);
                    }
                    mainPart = mainPart.substring(0, innerWIndex);
                }
            }
        } else {
            mainPart = cmdText;
            if (!orderBy.isEmpty()) {
                mainPart = cmdText.substring(0, oIndex);
            }
            if (!groupBy.isEmpty()) {
                mainPart = cmdText.substring(0, gIndex);
            }
        }

        allMainPart = mainPart;

        // 处理"select * from"的特殊情况
        if (mainPart.trim().toLowerCase().startsWith("select * from")) {
            mainPart = SEL_X_FROM_REG.matcher(mainPart).replaceAll("");
        }
    }


    /**
     * 处理UNION查询（标记为UNION并简化处理）
     */
    private void doAnalyzeUnion() {
        allMainPart = mainPart = cmdText;
        _isUnion = true;
    }


    /**
     * 分析查询字段（提取内置字段、别名、表.字段等）
     */
    public void DoAnalyzeSelPms() {
        if (QueryPart == null || QueryPart.isEmpty()) {
            return;
        }
        analyzedPms = true;

        String QueryPart = Pattern.compile(" as ", Pattern.MULTILINE).matcher(this.QueryPart).replaceAll(" ");

        // 初始化集合
        InnerPms.clear();
        AliasPms.clear();
        dotPms.clear();
        dotPmNames.clear();

        // 正则表达式：匹配表.字段（如t1.id）
        Pattern dotReg = Pattern.compile("[^\\(|\\)|\\+|\\-|\\*|\\/|\\,| |\\.]+?\\.[^\\(|\\)|\\+|\\-|\\*|\\/|\\,| |\\.|=]+");
        // 匹配内置字段（逗号间的字段）
        Pattern innerReg = Pattern.compile("(,){1}\\w+(,){1}");
        // 匹配别名字段（如... as alias）
        Pattern aliasReg = Pattern.compile("(\\)| )+\\w+(,)");

        Matcher dotMatcher = dotReg.matcher(QueryPart);
        Matcher innerMatcher = innerReg.matcher("," + QueryPart + ",");
        Matcher innerMatcher1 = innerReg.matcher("," + "zw_field_name" + "," + QueryPart + ","); // 占位符辅助匹配
        Matcher aliasMatcher = aliasReg.matcher(QueryPart + ",");

        // 提取表.字段（dotPms）
        while (dotMatcher.find()) {
            String val = dotMatcher.group();
            String[] parts = val.split("\\.");
            if (parts.length == 2) {
                String col = parts[1].toLowerCase();
                if (!dotPms.containsKey(col)) {
                    dotPms.put(col, parts[0]);
                    dotPmNames.add(val);
                }
            }
        }

        // 提取别名字段（AliasPms）
        while (aliasMatcher.find()) {
            String val = aliasMatcher.group().trim();
            val = val.replaceAll("[ )?,]+", ""); // 去除多余字符
            if (!val.isEmpty() && !AliasPms.contains(val)) {
                AliasPms.add(val);
            }
        }

        // 提取内置字段（InnerPms）
        while (innerMatcher.find()) {
            String val = innerMatcher.group().replaceAll(",", "").trim();
            if (!val.isEmpty() && !InnerPms.contains(val) && !AliasPms.contains(val)) {
                InnerPms.add(val);
            }
        }

        // 辅助占位符匹配
        while (innerMatcher1.find()) {
            String val = innerMatcher1.group().replaceAll(",", "").trim();
            if (!val.isEmpty() && !InnerPms.contains(val) && !AliasPms.contains(val)) {
                InnerPms.add(val);
            }
        }

        // 处理通配符*
        if (QueryPart.equals("*")) {
            InnerPms.add("*");
        }

        // 移除占位符
        InnerPms.remove("zw_field_name");
    }


    /**
     * 检查字符串是否包含表.字段
     */
    private boolean hasDotPms(String str) {
        for (String name : dotPmNames) {
            if (str.toLowerCase().contains(name.toLowerCase())) {
                return true;
            }
        }
        Pattern dotReg = Pattern.compile("[^\\(|\\)|\\+|\\-|\\*|\\/|\\,| |\\.]+?\\.[^\\(|\\)|\\+|\\-|\\*|\\/|\\,| |\\.|=]+");
        Matcher matcher = dotReg.matcher(str);
        if (matcher.find()) {
            String val = matcher.group();
            String[] parts = val.split("\\.");
            if (parts.length == 2 && dotPms.containsValue(parts[0])) {
                return true;
            }
        }
        return false;
    }


    /**
     * 检查别名是否包含指定字段
     */
    private boolean aliasContains(String key, String val) {
        key = key.toLowerCase();
        if (AliasPms.contains(key)) {
            return true;
        }
        String lowerVal = val.toLowerCase();
        for (String alias : AliasPms) {
            if (lowerVal.contains(" " + alias + " ")) {
                return true;
            }
        }
        return false;
    }


    /**
     * 动态插入WHERE条件
     *
     * @param where          条件键值对
     * @param inner          是否内置条件
     * @param ot             是否外置条件
     * @param removeOldWhere 是否移除原WHERE
     * @return 处理后的SQL
     */
    public String InsertWhere(Map<String, String> where, boolean inner, boolean ot, boolean removeOldWhere) {
        // 边界条件判断
        if (where == null || where.isEmpty()) {
            return cmdText;
        }
        if (QueryPart == null || QueryPart.isEmpty()) {
            return cmdText;
        }
        if (!analyzedPms) {
            DoAnalyzeSelPms(); // 假设存在此方法，用于解析查询参数
        }

        // 分类where条件为内部条件和外部条件
        Map<String, String> dinnerwhere = new LinkedHashMap<>();
        Map<String, String> doutwhere = new LinkedHashMap<>();

        for (Map.Entry<String, String> entry : where.entrySet()) {
            String key = entry.getKey().toLowerCase();
            String value = entry.getValue();

            if (!_isUnion) {
                // 判断是否属于外部条件
                if ((aliasContains(key, value) || ot) && !cmdText.trim().toLowerCase().startsWith("select * from")) {
                    doutwhere.put(key, value);
                } else {
                    dinnerwhere.put(key, value);
                }
            } else {
                // 包含UNION时，全部放入外部条件
                doutwhere.put(key, value);
            }
        }

        // 处理原有WHERE子句
        String oldWhereStr = (OldWhere == null || OldWhere.trim().equalsIgnoreCase("where")) ? "" : OldWhere;
        String innerWhere = String.join(" ", dinnerwhere.values()).trim();
        String outWhere = String.join(" ", doutwhere.values()).trim();

        // 处理需要移除旧WHERE或旧WHERE为空的情况2026.2.27
//        if ((removeOldWhere || (oldWhereStr.isEmpty() && getRegIndex(cmdText, "where", true) < 0
//                && (!innerWhere.isEmpty() || (inner && !outWhere.isEmpty()))) && !_isUnion)) {
//            oldWhereStr = "where 1=1 ";
//        }
        if (removeOldWhere || (oldWhereStr.isEmpty() && getRegIndex(cmdText, "where", true) < 0
                && (!innerWhere.isEmpty() || (inner && !outWhere.isEmpty()))) && !_isUnion) {
            oldWhereStr = "where 1=1 ";
        }

        // 处理包含ORDER BY的内部条件
        if (innerWhere.toLowerCase().contains("order by") && allMainPart.toLowerCase().indexOf(" top ") == -1) {
            oldWhereStr = String.format("%s %s %s", oldWhereStr, outWhere, innerWhere).trim();
            inner = true;
        }
        // 处理包含GROUP BY且有JOIN的特殊情况
        else if (outWhere.isEmpty() && (getRegIndex(groupBy + orderBy, "where", true) > -1)
                && (getRegIndex(cmdText, "join", true) > -1)) {
            return String.format("%s%n %s%n %s%n %s%n %s %s",
                    allMainPart, oldWhereStr, groupBy, having, orderBy, innerWhere);
        }
        // 常规条件合并
        else {
            oldWhereStr = String.format("%s %s %s", oldWhereStr, innerWhere, inner ? outWhere : "").trim();
        }

        // 清理ORDER BY中的重复内容
        if (oldWhereStr.toLowerCase().contains("order by")) {
            orderBy = orderBy.toLowerCase().replace("order by", "").trim();
        }

        // 生成最终SQL
        if (outWhere.isEmpty() || inner) {
            return String.format("%s%n %s%n %s%n %s%n %s",
                    allMainPart, oldWhereStr, groupBy, having, orderBy);
        }

        // 处理SELECT * FROM的特殊情况
        if (cmdText.trim().toLowerCase().startsWith("select * from ")) {
            if (!orderBy.isEmpty() || !groupBy.isEmpty()) {
                return String.format("%s%n %s%n %s%n %s%n %s%n%s",
                        allMainPart,
                        (OldWhere == null || OldWhere.isEmpty() || oldWhereStr.isEmpty()) ? "where 1=1 " : oldWhereStr,
                        outWhere, groupBy, having, orderBy);
            } else {
                return String.format("%s %s %s", cmdText,
                        (OldWhere == null || OldWhere.isEmpty() || oldWhereStr.isEmpty()) ? "where 1=1 " : "",
                        outWhere);
            }
        }

        // 默认情况：嵌套子查询处理外部条件
        return String.format("select * from (%s%n %s%n %s%n %s%n%s%n) PM_TEMP where 1=1 %s",
                BuildTopText(allMainPart, ""), oldWhereStr, groupBy, having, orderBy, outWhere);
        //return String.format("%s%n %s%n %s%n %s%n%s%n  %s",
        //buildTopText(allMainPart, ""), oldWhereStr, groupBy, having, orderBy, outWhere);
    }


    public String InsertWhere(Map<String, String> where, boolean inner) {
        return InsertWhere(where, inner, false, false);
    }

    /**
     * 构建分页查询SQL
     */
    public String buildSplitPageCmdText(int start, int pageSize, StringBuilder indexColName) {
        indexColName.setLength(0);
        indexColName.append("__RowIndex");
        if (withIndex >= 0 || !_isSelect) {
            return "";
        }

        String tempSql = "select *, ROW_NUMBER() over(order by getdate()) " + indexColName + " into #__tempdata from({0});\n" +
                "select count(1) from #__tempdata;\n" +
                "select top {1} * from #__tempdata where " + indexColName + ">{2};drop table #__tempdata;";

        String cmdText = BuildTopText(null, "");
        if (pageSize < 0) {
            pageSize = 1000000000;
        }
        return String.format(tempSql, cmdText.trim(), pageSize, start);
    }

    /**
     * 构建分页查询SQL语句（方式1）
     *
     * @param start        起始位置
     * @param pageSize     每页条数
     * @param indexColName 输出参数：行索引列名
     * @return 分页查询SQL
     */
    public String buildSplitPageCmdText1(int start, int pageSize, StringBuilder indexColName) {
        indexColName.setLength(0); // 清空 StringBuilder
        indexColName.append("__RowIndex"); // 设置行索引列名

        // 如果包含 WITH 子句或不是 SELECT 语句，返回空字符串
        if (withIndex >= 0 || !_isSelect) {
            return "";
        }

        // 处理默认页大小
        if (pageSize < 0) {
            pageSize = 1000000000;
        }

        // 构建包含行号的子查询SQL
        String cmdText = BuildTopText(null, "ROW_NUMBER() over(order by getdate()) __RowIndex,");
        // 去除可能的末尾分号
        cmdText = cmdText.replaceAll(";$", "");

        // 分页SQL模板
        String tempSql = "{0}select top {2} * from ({1}) __temp where {4} > {3}";

        // 格式化并返回最终SQL
        return String.format(tempSql,
                BuildCoutCmdText(),
                cmdText,
                pageSize,
                start,
                indexColName.toString());
    }

    /**
     * 构建带TOP的SQL（避免分页时的排序问题）
     */
    public String BuildTopText(String cmdText, String otherQuery) {
        String targetCmd = (cmdText == null) ? this.cmdText : cmdText;
        if (sIndex < 0) {
            return targetCmd;
        }

        if (targetCmd.toLowerCase().startsWith("select * from") || (!orderBy.isEmpty() && tIndex < 0)) {
            targetCmd = targetCmd.substring(0, sIndex) + " select top 1000000000 " + otherQuery + " " + targetCmd.substring(sIndex + "select".length());
        } else if (!otherQuery.isEmpty()) {
            targetCmd = targetCmd.substring(0, sIndex) + " select " + otherQuery + " " + targetCmd.substring(sIndex + "select".length());
        }

        return targetCmd;
    }

    public String BuildTopText() {
        return BuildTopText(null, "");
    }

    /**
     * 构建计数查询SQL（如count(1)）
     */
    public String BuildCoutCmdText(String aggCmd, boolean outer) {
        if (!_isSelect) {
            return "";
        }
        if (_isUnion || !groupBy.isEmpty() || sIndex > fIndex || outer) {
            String sql = "select " + aggCmd + " from (" + cmdText.substring(0, cmdText.length() - orderBy.length()) + " ) a;";
            return sql;
        } else {
            return "select " + aggCmd + "\r\n from " + fromPart + "\r\n " + OldWhere + "\r\n " + groupBy + "\r\n " + having + ";";
        }
    }

    // 简化调用：默认count(1) tot，非外部查询
    public String BuildCoutCmdText() {
        return BuildCoutCmdText("count(1) tot", false);
    }
}