package com.gzzm.lobster.tool.mcp;

import com.gzzm.lobster.common.JsonUtil;
import com.gzzm.lobster.common.ToolRiskLevel;

import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

final class McpClientSupport {
    private McpClientSupport() {}

    @SuppressWarnings("unchecked")
    static List<McpToolSpec> parseToolList(Map<String, Object> result, ToolRiskLevel defaultRisk) {
        Object toolsObj = result == null ? null : result.get("tools");
        if (!(toolsObj instanceof Iterable)) return Collections.emptyList();
        List<McpToolSpec> out = new ArrayList<>();
        for (Object item : (Iterable<?>) toolsObj) {
            if (!(item instanceof Map)) continue;
            Map<String, Object> m = (Map<String, Object>) item;
            String name = str(m.get("name"));
            if (name == null || name.trim().isEmpty()) continue;
            McpToolSpec spec = new McpToolSpec();
            spec.setName(name);
            spec.setTitle(str(m.get("title")));
            spec.setDescription(str(m.get("description")));
            spec.setInputSchema(asMap(m.get("inputSchema")));
            spec.setOutputSchema(asMap(m.get("outputSchema")));
            Map<String, Object> annotations = asMap(m.get("annotations"));
            spec.setAnnotations(annotations);
            ToolRiskLevel risk = parseRisk(annotations.get("riskLevel"), defaultRisk);
            spec.setRiskLevel(risk);
            spec.setRequireConfirm(Boolean.TRUE.equals(annotations.get("requireConfirm"))
                    || risk == ToolRiskLevel.WRITE
                    || risk == ToolRiskLevel.BATCH_WRITE
                    || risk == ToolRiskLevel.DESTRUCTIVE);
            out.add(spec);
        }
        return out;
    }

    @SuppressWarnings("unchecked")
    static McpCallResult parseCallResult(Map<String, Object> result) {
        McpCallResult out = new McpCallResult();
        if (result == null) {
            return McpCallResult.error("empty MCP result");
        }
        out.setError(Boolean.TRUE.equals(result.get("isError")));
        Object content = result.get("content");
        if (content instanceof List) out.setContent((List<Object>) content);
        out.setStructuredContent(result.get("structuredContent"));
        out.setAnnotations(asMap(result.get("annotations")));
        out.setMessage(firstText(out.getContent(), out.getAnnotations()));
        return out;
    }

    @SuppressWarnings("unchecked")
    static Map<String, Object> asMap(Object value) {
        if (value instanceof Map) return (Map<String, Object>) value;
        return Collections.emptyMap();
    }

    static String textFromCallResult(McpCallResult result) {
        if (result == null) return "";
        String m = result.getMessage();
        if (m != null && !m.isEmpty()) return m;
        if (result.getStructuredContent() != null) return JsonUtil.toJson(result.getStructuredContent());
        if (result.getContent() != null && !result.getContent().isEmpty()) return JsonUtil.toJson(result.getContent());
        return result.isError() ? "MCP tool returned error" : "MCP tool returned empty result";
    }

    static Map<String, Object> dataFromCallResult(McpCallResult result) {
        Map<String, Object> data = new LinkedHashMap<>();
        if (result == null) return data;
        data.put("content", result.getContent());
        if (result.getStructuredContent() != null) data.put("structuredContent", result.getStructuredContent());
        if (result.getAnnotations() != null && !result.getAnnotations().isEmpty()) {
            data.put("annotations", result.getAnnotations());
        }
        return data;
    }

    static ToolRiskLevel parseRisk(Object value, ToolRiskLevel fallback) {
        if (value == null) return fallback == null ? ToolRiskLevel.READ_ONLY : fallback;
        try {
            return ToolRiskLevel.valueOf(String.valueOf(value));
        } catch (Throwable ignore) {
            return fallback == null ? ToolRiskLevel.READ_ONLY : fallback;
        }
    }

    private static String firstText(List<Object> content, Map<String, Object> annotations) {
        if (content != null) {
            for (Object item : content) {
                if (item instanceof Map) {
                    Object text = ((Map<?, ?>) item).get("text");
                    if (text != null) return String.valueOf(text);
                }
            }
        }
        Object err = annotations == null ? null : annotations.get("errorMessage");
        return err == null ? null : String.valueOf(err);
    }

    private static String str(Object value) {
        return value == null ? null : String.valueOf(value);
    }
}
