package com.huangzj.protoplugin;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 从 proto 文本解析 {@code PbService} 与 {@code ServiceN_Method}，供生成 {@code PbService.Service_k_VALUE} /
 * {@code ServiceN_Method.MethodJ_VALUE}。
 */
public final class ProtoEnumResolver {

    private static final Pattern ENUM_ENTRY = Pattern.compile("(\\w+)\\s*=\\s*(\\d+)\\s*;?");

    private ProtoEnumResolver() {}

    /** service 序号（如 1）→ PbService 枚举常量名（如 Service_1）。 */
    public static Map<Integer, String> parsePbServiceByNumber(String pbServiceProtoContent) {
        Map<Integer, String> map = new HashMap<>();
        Matcher em = Pattern.compile("enum\\s+PbService\\s*\\{([^}]+)\\}", Pattern.DOTALL)
                .matcher(pbServiceProtoContent);
        if (!em.find()) {
            return map;
        }
        String body = em.group(1);
        Matcher m = ENUM_ENTRY.matcher(body);
        while (m.find()) {
            String name = m.group(1);
            int num = Integer.parseInt(m.group(2));
            if ("Default".equals(name) || num == 0) {
                continue;
            }
            map.put(num, name);
        }
        return map;
    }

    /**
     * 解析 {@code ServiceN_Method}：去掉 Default*，按数值排序，第 i 个（从 0 起）对应同 service 内第 i 条 rpc。
     */
    public static List<String> orderedMethodConstantNames(String cmdRpcContent, int serviceNumber) {
        Pattern p = Pattern.compile(
                "enum\\s+Service" + serviceNumber + "_Method\\s*\\{([^}]+)\\}", Pattern.DOTALL);
        Matcher em = p.matcher(cmdRpcContent);
        if (!em.find()) {
            return List.of();
        }
        String body = em.group(1);
        List<NameValue> list = new ArrayList<>();
        Matcher m = ENUM_ENTRY.matcher(body);
        while (m.find()) {
            String name = m.group(1);
            int val = Integer.parseInt(m.group(2));
            if (name.startsWith("Default")) {
                continue;
            }
            list.add(new NameValue(name, val));
        }
        list.sort(Comparator.comparingInt(nv -> nv.value));
        return list.stream().map(nv -> nv.name).toList();
    }

    public static String resolvePbServiceConstant(Map<Integer, String> byNumber, int serviceIndex) {
        String name = byNumber.get(serviceIndex);
        if (name != null) {
            return name;
        }
        return "Service_" + serviceIndex;
    }

    private record NameValue(String name, int value) {}
}
