package com.yd.csf.api.utils;

import java.util.*;
import java.util.regex.*;

/**
 * 公式解析工具类
 */
public class FormulaParser {

    /**
     * 从公式字符串中解析出所有变量业务ID
     * @param calculationFormulaBizId 公式字符串，如 "(variable_1001 + variable_2123) * variable_4455"
     * @return 变量业务ID的集合
     */
    public static Set<String> parseVariableBizIds(String calculationFormulaBizId) {
        Set<String> variableIds = new HashSet<>();

        if (calculationFormulaBizId == null || calculationFormulaBizId.trim().isEmpty()) {
            return variableIds;
        }

        // 修改正则表达式以匹配新的变量ID格式（包含字母和数字）
        Pattern pattern = Pattern.compile("variable_[a-zA-Z0-9]+");
        Matcher matcher = pattern.matcher(calculationFormulaBizId);

        while (matcher.find()) {
            variableIds.add(matcher.group());
        }

        return variableIds;
    }

    /**
     * 从公式字符串中解析出所有变量业务ID（返回列表，保持顺序）
     * @param calculationFormulaBizId 公式字符串
     * @return 变量业务ID的列表（按出现顺序）
     */
    public static List<String> parseVariableBizIdsOrdered(String calculationFormulaBizId) {
        List<String> variableIds = new ArrayList<>();

        if (calculationFormulaBizId == null || calculationFormulaBizId.trim().isEmpty()) {
            return variableIds;
        }

        // 修改正则表达式以匹配新的变量ID格式（包含字母和数字）
        Pattern pattern = Pattern.compile("variable_[a-zA-Z0-9]+");
        Matcher matcher = pattern.matcher(calculationFormulaBizId);

        while (matcher.find()) {
            variableIds.add(matcher.group());
        }

        return variableIds;
    }

    /**
     * 从公式字符串中解析出纯数字ID部分
     * @param calculationFormulaBizId 公式字符串
     * @return 纯数字ID的集合
     */
    public static Set<Long> parseVariableNumericIds(String calculationFormulaBizId) {
        Set<Long> numericIds = new HashSet<>();

        if (calculationFormulaBizId == null || calculationFormulaBizId.trim().isEmpty()) {
            return numericIds;
        }

        // 匹配 variable_ 后面的字母数字部分（由于新格式可能包含字母，此方法可能不再适用）
        Pattern pattern = Pattern.compile("variable_([a-zA-Z0-9]+)");
        Matcher matcher = pattern.matcher(calculationFormulaBizId);

        while (matcher.find()) {
            try {
                // 注意：新格式可能包含字母，无法直接转换为Long
                // 这里保留原有逻辑，但实际可能返回空集合
                String idPart = matcher.group(1);
                if (idPart.matches("\\d+")) {
                    Long numericId = Long.parseLong(idPart);
                    numericIds.add(numericId);
                }
            } catch (NumberFormatException e) {
                // 忽略格式错误的ID
                System.err.println("无效的数字ID: " + matcher.group(1));
            }
        }

        return numericIds;
    }
    
    /**
     * 替换公式中的变量业务ID为实际值
     * @param formula 原始公式
     * @param variableValues 变量值映射表
     * @return 替换后的公式
     */
    public static String replaceVariablesWithValues(String formula, Map<String, Double> variableValues) {
        if (formula == null || variableValues == null) {
            return formula;
        }
        
        String result = formula;
        for (Map.Entry<String, Double> entry : variableValues.entrySet()) {
            String variableId = entry.getKey();
            Double value = entry.getValue();
            
            if (value != null) {
                // 直接替换变量ID为数值
                result = result.replace(variableId, value.toString());
            }
        }
        
        return result;
    }
    
    /**
     * 验证公式格式是否正确
     * @param formula 公式字符串
     * @return 验证结果
     */
    public static boolean validateFormulaFormat(String formula) {
        if (formula == null || formula.trim().isEmpty()) {
            return false;
        }
        
        // 基本格式检查：包含变量、运算符和括号
        // 这里可以添加更复杂的验证逻辑
        String tempFormula = formula.replaceAll("variable_\\d+", "VAR")
                                   .replaceAll("\\s+", "");
        
        // 简单的括号匹配检查
        return isBracketBalanced(tempFormula);
    }
    
    /**
     * 检查括号是否平衡
     */
    private static boolean isBracketBalanced(String str) {
        Deque<Character> stack = new ArrayDeque<>();
        
        for (char c : str.toCharArray()) {
            if (c == '(') {
                stack.push(c);
            } else if (c == ')') {
                if (stack.isEmpty() || stack.pop() != '(') {
                    return false;
                }
            }
        }
        
        return stack.isEmpty();
    }
}