package com.gzzm.lobster.tool.mcp;

import com.gzzm.lobster.tool.ToolNamePolicy;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;

/**
 * Maps remote MCP tool names to provider-safe Lobster tool names.
 */
public final class McpToolNameMapper {

    private McpToolNameMapper() {}

    public static String localToolName(McpServerConfig server, String remoteName) {
        String ns = firstNonBlank(server == null ? null : server.getNamespace(),
                server == null ? null : server.getServerId());
        String name = sanitizePart(ns, "mcp") + "_" + sanitizePart(remoteName, "tool");
        if (name.length() <= ToolNamePolicy.MAX_LLM_TOOL_NAME_LENGTH) return name;
        String suffix = "_" + shortHash(ns + "\n" + remoteName);
        int keep = Math.max(1, ToolNamePolicy.MAX_LLM_TOOL_NAME_LENGTH - suffix.length());
        return name.substring(0, keep) + suffix;
    }

    public static String sanitizePart(String raw, String fallback) {
        String s = raw == null ? "" : raw.trim();
        StringBuilder out = new StringBuilder();
        boolean lastSeparator = false;
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            if (ToolNamePolicy.isAllowedLlmToolNameChar(c)) {
                out.append(c);
                lastSeparator = false;
            } else if (!lastSeparator && out.length() > 0) {
                out.append('_');
                lastSeparator = true;
            }
        }
        while (out.length() > 0 && out.charAt(out.length() - 1) == '_') {
            out.deleteCharAt(out.length() - 1);
        }
        return out.length() == 0 ? fallback : out.toString();
    }

    private static String shortHash(String raw) {
        try {
            MessageDigest digest = MessageDigest.getInstance("SHA-256");
            byte[] bytes = digest.digest(String.valueOf(raw).getBytes(StandardCharsets.UTF_8));
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < bytes.length && i < 6; i++) sb.append(String.format("%02x", bytes[i] & 0xff));
            return sb.toString();
        } catch (Throwable t) {
            return "hash";
        }
    }

    private static String firstNonBlank(String a, String b) {
        return a == null || a.trim().isEmpty() ? b : a;
    }
}
