package cn.nianxx.thhotel.integrations.mcp.superagent.service.impl;

import cn.nianxx.thhotel.integrations.mcp.superagent.common.dto.SuperAgentMcpSubmitPayloadAdaptation;
import cn.nianxx.thhotel.integrations.mcp.superagent.service.SuperAgentMcpSubmitPayloadAdapter;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.springframework.stereotype.Service;

/**
 * SuperAgent MCP 写入工具 payload 适配实现。该类只处理 transport 映射，不重新解释业务语义。
 */
@Service
public class SuperAgentMcpSubmitPayloadAdapterImpl implements SuperAgentMcpSubmitPayloadAdapter {

    private static final String ERROR_CODE = "MCP_SUBMIT_PAYLOAD_INVALID";
    private static final Set<String> V3_BUSINESS_ROOT_FIELDS = Set.of(
            "source_message",
            "message_events",
            "case_candidates",
            "extraction_warnings",
            "unhandled_current_intents",
            "hotel_id",
            "source_provider",
            "source_channel");
    private static final Set<String> V3_TRANSPORT_COMPATIBILITY_ROOT_FIELDS = Set.of(
            "hotel_id",
            "source_provider",
            "source_channel");
    private static final Set<String> V3_SOURCE_MESSAGE_FIELDS = Set.of(
            "source_message_id",
            "subject",
            "from",
            "cc",
            "received_at",
            "source_channel");
    private static final List<String> V3_SOURCE_MESSAGE_REQUIRED_FIELDS = List.of(
            "source_message_id",
            "subject",
            "from",
            "cc",
            "received_at",
            "source_channel");
    private static final Set<String> V3_EVENT_FIELDS = Set.of(
            "event_type",
            "event_role",
            "source_event_index",
            "current_or_history",
            "case_keys",
            "relevant_message_excerpt",
            "attachments",
            "file_references",
            "context_used",
            "extracted_fields",
            "manual_review",
            "related_event_type",
            "requires_downstream_hard_validation",
            "related_source_event_index",
            "related_source_event_indices",
            "parent_source_event_index",
            "linked_task_group_id",
            "blocked_until_parent_completed",
            "contract_errors",
            "missing_fields",
            "relationship_type");
    private static final List<String> V3_EVENT_TRANSPORT_REQUIRED_FIELDS = List.of(
            "source_event_index");
    private static final Set<String> V3_NOTIFICATION_ROOT_FIELDS = Set.of(
            "source_message",
            "route_code",
            "handler_type",
            "result_type",
            "current_or_history",
            "agent_assessment",
            "notification",
            "manual_review",
            "hotel_id",
            "source_provider",
            "source_channel");
    private static final List<String> V3_NOTIFICATION_REQUIRED_FIELDS = List.of(
            "source_message",
            "route_code",
            "handler_type",
            "result_type",
            "current_or_history",
            "agent_assessment",
            "notification",
            "manual_review");
    private static final Set<String> LEGACY_V2_ROOT_FIELDS = Set.of(
            "hotel_id",
            "source_provider",
            "source_channel",
            "source_message_id",
            "ai_task_results",
            "extraction_warnings");
    private static final Set<String> LEGACY_V2_ITEM_FIELDS = Set.of(
            "source_event_index",
            "catalog_code",
            "skill_id",
            "result_type",
            "task_type",
            "task_subtype",
            "current_or_history",
            "case_keys",
            "visible_reason",
            "relevant_message_excerpt",
            "attachments",
            "file_references",
            "context_used",
            "extracted_fields",
            "manual_review",
            "informational_message",
            "additional_operations",
            "idempotency_key");
    private static final List<String> LEGACY_V2_ITEM_REQUIRED_FIELDS = List.of(
            "source_event_index",
            "catalog_code",
            "skill_id",
            "result_type",
            "task_type");
    private static final Set<String> LEGACY_V2_RESULT_TYPES = Set.of(
            "normal_task",
            "manual_review",
            "informational_message");
    private static final List<String> REQUIRED_V3_ROOT_ARRAY_FIELDS = List.of(
            "message_events",
            "case_candidates",
            "extraction_warnings",
            "unhandled_current_intents");

    private final ObjectMapper objectMapper;

    /**
     * 注入 JSON 工具，用于深拷贝和构造归一化 payload。
     */
    public SuperAgentMcpSubmitPayloadAdapterImpl(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }

    /**
     * 根据 submit arguments 的根结构选择 V3 业务根、S10/S99 通知或 V2 兼容映射。
     */
    @Override
    public SuperAgentMcpSubmitPayloadAdaptation adapt(JsonNode arguments) {
        if (arguments == null || !arguments.isObject()) {
            throw invalid("MCP submit arguments 必须是 JSON object。", "arguments");
        }
        if (isV3BusinessRoot(arguments)) {
            if (isV3SourceMessageIdentityMissing(arguments)) {
                return new SuperAgentMcpSubmitPayloadAdaptation(arguments, Map.of());
            }
            return adaptV3BusinessRoot(arguments);
        }
        if (isV3SourceMessageNotification(arguments)) {
            if (isV3SourceMessageIdentityMissing(arguments)) {
                return new SuperAgentMcpSubmitPayloadAdaptation(arguments, Map.of());
            }
            validateRootFields(arguments, V3_NOTIFICATION_ROOT_FIELDS);
            validateRequiredFields(arguments, V3_NOTIFICATION_REQUIRED_FIELDS);
            validateSourceMessage(arguments.path("source_message"));
            return new SuperAgentMcpSubmitPayloadAdaptation(removeCompatibilityFields(arguments), Map.of());
        }
        if (arguments.has("ai_task_results")) {
            validateRootFields(arguments, LEGACY_V2_ROOT_FIELDS);
            if (!hasText(arguments.path("source_message_id"))) {
                throw invalid("V2 兼容 payload 缺少 source_message_id。", "source_message_id");
            }
            if (!arguments.path("ai_task_results").isArray()) {
                throw invalid("ai_task_results 必须是数组。", "ai_task_results");
            }
            validateLegacyV2Items(arguments.path("ai_task_results"));
            validateLegacyExtractionWarnings(arguments);
            return new SuperAgentMcpSubmitPayloadAdaptation(arguments, Map.of());
        }
        throw invalid("MCP submit arguments 不是支持的 V3 或 V2 任务结果结构。", "arguments");
    }

    /**
     * 校验并转换 V3 业务根，将业务事件 ID 映射为本系统一基 source_event_index。
     */
    private SuperAgentMcpSubmitPayloadAdaptation adaptV3BusinessRoot(JsonNode root) {
        validateRootFields(root, V3_BUSINESS_ROOT_FIELDS);
        validateSourceMessage(root.path("source_message"));
        for (String fieldName : REQUIRED_V3_ROOT_ARRAY_FIELDS) {
            if (!root.path(fieldName).isArray()) {
                throw invalid(fieldName + " 必须是数组。", fieldName);
            }
        }
        ArrayNode events = (ArrayNode) root.path("message_events");
        if (events.isEmpty()) {
            return new SuperAgentMcpSubmitPayloadAdaptation(removeCompatibilityFields(root), Map.of());
        }
        Map<String, Integer> eventIndexMap = eventIndexMap(events);
        ObjectNode mappedRoot = removeCompatibilityFields(root);
        ArrayNode mappedEvents = (ArrayNode) mappedRoot.path("message_events");
        for (int index = 0; index < mappedEvents.size(); index++) {
            JsonNode eventNode = mappedEvents.get(index);
            if (!eventNode.isObject()) {
                throw invalid("message_events[] item 必须是 object。", "message_events");
            }
            ObjectNode event = (ObjectNode) eventNode;
            validateRootFields(event, V3_EVENT_FIELDS);
            validateRequiredFields(event, V3_EVENT_TRANSPORT_REQUIRED_FIELDS);
            if (!hasText(event.path("source_event_index"))) {
                throw invalid("message_events[].source_event_index 不能为空。", "source_event_index");
            }
            event.put("source_event_index", index + 1);
            mapSingleEventReference(event, eventIndexMap, "related_source_event_index", false);
            mapSingleEventReference(event, eventIndexMap, "parent_source_event_index", true);
            mapMultipleEventReferences(event, eventIndexMap);
        }
        return new SuperAgentMcpSubmitPayloadAdaptation(
                mappedRoot,
                Map.of(
                        "mapping_policy", "message_events_array_order_1_based",
                        "source_event_index_mapping", sourceEventIndexMapping(eventIndexMap)));
    }

    /**
     * 构建业务事件 ID 到 MCP 一基索引的映射，重复或缺失立即拒绝。
     */
    private Map<String, Integer> eventIndexMap(ArrayNode events) {
        Map<String, Integer> result = new LinkedHashMap<>();
        for (int index = 0; index < events.size(); index++) {
            JsonNode event = events.get(index);
            if (!event.isObject()) {
                throw invalid("message_events[] item 必须是 object。", "message_events");
            }
            validateRootFields(event, V3_EVENT_FIELDS);
            validateRequiredFields(event, V3_EVENT_TRANSPORT_REQUIRED_FIELDS);
            String rawIndex = referenceText(event.path("source_event_index"));
            if (rawIndex == null) {
                throw invalid("message_events[].source_event_index 不能为空。", "source_event_index");
            }
            if (result.putIfAbsent(rawIndex, index + 1) != null) {
                throw invalid("message_events[].source_event_index 不能重复。", "source_event_index");
            }
        }
        return result;
    }

    /**
     * 构造原始业务事件 ID 到本系统一基索引的映射诊断。
     */
    private List<Map<String, Object>> sourceEventIndexMapping(Map<String, Integer> eventIndexMap) {
        List<Map<String, Object>> result = new ArrayList<>();
        for (Map.Entry<String, Integer> entry : eventIndexMap.entrySet()) {
            Map<String, Object> mapping = new LinkedHashMap<>();
            mapping.put("original_source_event_index", entry.getKey());
            mapping.put("mapped_source_event_index", entry.getValue());
            result.add(mapping);
        }
        return result;
    }

    /**
     * 映射单事件关系字段；parent_source_event_index 按业务入站服务约定输出数字。
     */
    private void mapSingleEventReference(
            ObjectNode event,
            Map<String, Integer> eventIndexMap,
            String fieldName,
            boolean numericOutput) {
        JsonNode value = event.get(fieldName);
        if (value == null || value.isNull()) {
            return;
        }
        Integer mappedIndex = eventIndexMap.get(referenceText(value));
        if (mappedIndex == null) {
            throw invalid(fieldName + " 引用了不存在的 source_event_index。", fieldName);
        }
        if (numericOutput) {
            event.put(fieldName, mappedIndex);
        } else {
            event.put(fieldName, String.valueOf(mappedIndex));
        }
    }

    /**
     * 映射多事件关系字段，保持顺序并拒绝悬空或重复引用。
     */
    private void mapMultipleEventReferences(ObjectNode event, Map<String, Integer> eventIndexMap) {
        JsonNode indices = event.get("related_source_event_indices");
        if (indices == null || indices.isNull()) {
            return;
        }
        if (!indices.isArray()) {
            throw invalid("related_source_event_indices 必须是数组。", "related_source_event_indices");
        }
        ArrayNode mapped = objectMapper.createArrayNode();
        Set<Integer> seen = new LinkedHashSet<>();
        for (JsonNode item : indices) {
            Integer mappedIndex = eventIndexMap.get(referenceText(item));
            if (mappedIndex == null) {
                throw invalid("related_source_event_indices 引用了不存在的 source_event_index。", "related_source_event_indices");
            }
            if (!seen.add(mappedIndex)) {
                throw invalid("related_source_event_indices 不能包含重复引用。", "related_source_event_indices");
            }
            mapped.add(String.valueOf(mappedIndex));
        }
        event.set("related_source_event_indices", mapped);
    }

    /**
     * 校验 source_message 的最小形态，source_message_id 必须存在。
     */
    private void validateSourceMessage(JsonNode sourceMessage) {
        if (sourceMessage == null || !sourceMessage.isObject()) {
            throw invalid("source_message 必须是对象。", "source_message");
        }
        validateRootFields(sourceMessage, V3_SOURCE_MESSAGE_FIELDS);
        validateRequiredFields(sourceMessage, V3_SOURCE_MESSAGE_REQUIRED_FIELDS);
        if (!hasText(sourceMessage.path("source_message_id"))) {
            throw invalid("source_message.source_message_id 不能为空。", "source_message.source_message_id");
        }
        if (!isStringOrNull(sourceMessage.path("subject"))
                || !isStringOrNull(sourceMessage.path("from"))
                || !isStringArray(sourceMessage.path("cc"))
                || !isStringOrNull(sourceMessage.path("received_at"))
                || !"Email".equals(referenceText(sourceMessage.path("source_channel")))) {
            throw invalid("source_message 结构不符合 0711 P0 契约。", "source_message");
        }
    }

    /**
     * 校验 V2 兼容 item 完整结构，避免 MCP 调用方发送半结构化对象后才落到业务层失败。
     */
    private void validateLegacyV2Items(JsonNode taskResults) {
        for (JsonNode item : taskResults) {
            if (item == null || !item.isObject()) {
                throw invalid("ai_task_results[] item 必须是 object。", "ai_task_results");
            }
            validateRootFields(item, LEGACY_V2_ITEM_FIELDS);
            validateLegacyV2RequiredFields(item);
            validateLegacyV2Item((ObjectNode) item);
        }
    }

    /**
     * 校验对象不存在未知字段，避免 Agent 猜测 transport 字段。
     */
    private void validateRootFields(JsonNode node, Set<String> allowedFields) {
        if (node == null || !node.isObject()) {
            throw invalid("payload 节点必须是对象。", "payload");
        }
        Iterator<String> fieldNames = node.fieldNames();
        while (fieldNames.hasNext()) {
            String fieldName = fieldNames.next();
            if (!allowedFields.contains(fieldName)) {
                throw invalid("MCP submit payload 包含未知字段。", fieldName);
            }
        }
    }

    /**
     * 校验必填字段存在，允许字段值为 null 的场景由后续类型校验处理。
     */
    private void validateRequiredFields(JsonNode node, List<String> requiredFields) {
        for (String requiredField : requiredFields) {
            if (!node.has(requiredField)) {
                throw invalid("MCP submit payload 缺少必填字段。", requiredField);
            }
        }
    }

    /**
     * 校验 V2 兼容 item 的字段类型、允许值和常见子对象形态。
     */
    private void validateLegacyV2Item(ObjectNode item) {
        if (!hasText(item.path("source_event_index"))) {
            throw invalid("ai_task_results[].source_event_index 不能为空。", "ai_task_results[].source_event_index");
        }
        validateText(item, "catalog_code");
        validateText(item, "skill_id");
        validateText(item, "result_type");
        validateText(item, "task_type");
        if (!LEGACY_V2_RESULT_TYPES.contains(referenceText(item.path("result_type")))) {
            throw invalid("ai_task_results[].result_type 不在允许范围。", "ai_task_results[].result_type");
        }
        validateOptionalText(item, "task_subtype");
        validateOptionalText(item, "current_or_history");
        validateOptionalText(item, "visible_reason");
        validateOptionalText(item, "relevant_message_excerpt");
        validateOptionalText(item, "idempotency_key");
        validateOptionalObject(item, "case_keys");
        validateOptionalObject(item, "context_used");
        validateOptionalObject(item, "extracted_fields");
        validateOptionalObjectOrNull(item, "manual_review");
        validateOptionalObjectOrNull(item, "informational_message");
        validateOptionalArray(item, "attachments");
        validateOptionalArray(item, "file_references");
        validateOptionalArray(item, "additional_operations");
    }

    /**
     * 校验 V2 item 必填字段，并返回包含数组路径的错误字段名。
     */
    private void validateLegacyV2RequiredFields(JsonNode item) {
        for (String requiredField : LEGACY_V2_ITEM_REQUIRED_FIELDS) {
            if (!item.has(requiredField)) {
                throw invalid(
                        "MCP submit payload 缺少必填字段。",
                        "ai_task_results[]." + requiredField);
            }
        }
    }

    /**
     * 校验 V2 根级 extraction_warnings，存在时必须是数组。
     */
    private void validateLegacyExtractionWarnings(JsonNode arguments) {
        JsonNode extractionWarnings = arguments.get("extraction_warnings");
        if (extractionWarnings != null && !extractionWarnings.isArray()) {
            throw invalid("extraction_warnings 必须是数组。", "extraction_warnings");
        }
    }

    /**
     * 校验 V2 必填文本字段。
     */
    private void validateText(ObjectNode item, String fieldName) {
        if (!hasText(item.path(fieldName))) {
            throw invalid("ai_task_results[]." + fieldName + " 不能为空。", "ai_task_results[]." + fieldName);
        }
    }

    /**
     * 校验 V2 可选文本字段。
     */
    private void validateOptionalText(ObjectNode item, String fieldName) {
        JsonNode value = item.get(fieldName);
        if (value != null && !isStringOrNull(value)) {
            throw invalid("ai_task_results[]." + fieldName + " 必须是字符串或 null。", "ai_task_results[]." + fieldName);
        }
    }

    /**
     * 校验 V2 可选对象字段。
     */
    private void validateOptionalObject(ObjectNode item, String fieldName) {
        JsonNode value = item.get(fieldName);
        if (value != null && !value.isObject()) {
            throw invalid("ai_task_results[]." + fieldName + " 必须是 object。", "ai_task_results[]." + fieldName);
        }
    }

    /**
     * 校验 V2 可选对象或 null 字段。
     */
    private void validateOptionalObjectOrNull(ObjectNode item, String fieldName) {
        JsonNode value = item.get(fieldName);
        if (value != null && !value.isObject() && !value.isNull()) {
            throw invalid("ai_task_results[]." + fieldName + " 必须是 object 或 null。", "ai_task_results[]." + fieldName);
        }
    }

    /**
     * 校验 V2 可选数组字段。
     */
    private void validateOptionalArray(ObjectNode item, String fieldName) {
        JsonNode value = item.get(fieldName);
        if (value != null && !value.isArray()) {
            throw invalid("ai_task_results[]." + fieldName + " 必须是数组。", "ai_task_results[]." + fieldName);
        }
    }

    /**
     * 判断是否为 V3 业务根。
     */
    private boolean isV3BusinessRoot(JsonNode arguments) {
        return arguments.has("message_events");
    }

    /**
     * 判断是否为 V3 S10/S99 入口通知。
     */
    private boolean isV3SourceMessageNotification(JsonNode arguments) {
        return arguments.has("route_code") || arguments.has("result_type");
    }

    /**
     * source_message_id 缺失由业务入站服务返回既有 typed infrastructure error，MCP adapter 不改写错误通道。
     */
    private boolean isV3SourceMessageIdentityMissing(JsonNode arguments) {
        JsonNode sourceMessage = arguments.get("source_message");
        return sourceMessage == null
                || !sourceMessage.isObject()
                || !hasText(sourceMessage.path("source_message_id"));
    }

    /**
     * 移除 MCP transport 兼容字段，避免进入业务入站 exact root 校验。
     */
    private ObjectNode removeCompatibilityFields(JsonNode root) {
        ObjectNode copy = root.deepCopy();
        for (String fieldName : V3_TRANSPORT_COMPATIBILITY_ROOT_FIELDS) {
            copy.remove(fieldName);
        }
        return copy;
    }

    /**
     * 提取事件引用文本，数字和字符串都统一成字符串键。
     */
    private String referenceText(JsonNode node) {
        if (node == null || node.isNull()) {
            return null;
        }
        String value = node.asText();
        return value == null || value.trim().isEmpty() ? null : value.trim();
    }

    /**
     * 判断 JSON 文本节点是否存在有效内容。
     */
    private boolean hasText(JsonNode node) {
        return referenceText(node) != null;
    }

    /**
     * 判断字段是否为字符串或 null。
     */
    private boolean isStringOrNull(JsonNode node) {
        return node != null && (node.isTextual() || node.isNull());
    }

    /**
     * 判断数组是否只包含字符串。
     */
    private boolean isStringArray(JsonNode node) {
        if (node == null || !node.isArray()) {
            return false;
        }
        for (JsonNode item : node) {
            if (!item.isTextual()) {
                return false;
            }
        }
        return true;
    }

    /**
     * 构造稳定 MCP submit payload 校验异常。
     */
    private SuperAgentMcpSubmitPayloadException invalid(String message, String field) {
        return new SuperAgentMcpSubmitPayloadException(ERROR_CODE, message, field);
    }
}
