package cn.nianxx.thhotel.integrations.messaging.agentbus.adapter;

import cn.nianxx.thhotel.platform.message.common.request.CaptureSourceMessageCommand;
import cn.nianxx.thhotel.platform.message.common.result.SourceMessageCaptureResult;
import cn.nianxx.thhotel.platform.message.service.SourceMessageCaptureService;
import cn.nianxx.thhotel.platform.hotel.service.HotelContextService;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.nio.charset.StandardCharsets;
import java.util.Set;
import org.springframework.stereotype.Component;

/**
 * AgentBus 入站 frame 处理器。只负责控制事件识别和 SourceMessage 捕获，不做业务写操作或客户回复。
 */
@Component
public class AgentBusFrameProcessor {

    private static final String FRAME_TOO_LARGE = "FRAME_TOO_LARGE";
    private static final String INVALID_JSON = "INVALID_JSON";
    private static final String CAPTURE_FAILED = "CAPTURE_FAILED";
    private static final Set<String> CONTROL_EVENTS = Set.of("session.ready", "task.progress", "task.result");

    private final ObjectMapper objectMapper;
    private final AgentBusSourceMessageAdapter sourceMessageAdapter;
    private final SourceMessageCaptureService captureService;
    private final AgentBusConnectionStatus status;
    private final AgentBusProperties properties;
    private final HotelContextService hotelContextService;

    /**
     * 注入 AgentBus frame 处理依赖。外部协议转换与平台捕获服务通过稳定命令隔离。
     */
    public AgentBusFrameProcessor(
            ObjectMapper objectMapper,
            AgentBusSourceMessageAdapter sourceMessageAdapter,
            SourceMessageCaptureService captureService,
            AgentBusConnectionStatus status,
            AgentBusProperties properties,
            HotelContextService hotelContextService) {
        this.objectMapper = objectMapper;
        this.sourceMessageAdapter = sourceMessageAdapter;
        this.captureService = captureService;
        this.status = status;
        this.properties = properties;
        this.hotelContextService = hotelContextService;
    }

    /**
     * 处理一条 AgentBus raw frame。该方法不保存 raw frame，也不会发送 ACK 或客户回复。
     */
    public AgentBusFrameProcessResult process(String rawFrame) {
        status.markFrameReceived();
        if (rawFrame == null || rawFrame.getBytes(StandardCharsets.UTF_8).length > properties.getMaxFrameBytes()) {
            status.markFrameRejected(FRAME_TOO_LARGE, "AgentBus frame exceeds max allowed bytes.");
            return AgentBusFrameProcessResult.rejected(FRAME_TOO_LARGE);
        }
        JsonNode frame = parse(rawFrame);
        if (frame == null) {
            return AgentBusFrameProcessResult.failed(INVALID_JSON);
        }
        String eventType = firstText(frame, "type", frame, "event");
        if (eventType != null && CONTROL_EVENTS.contains(eventType)) {
            if ("session.ready".equals(eventType)) {
                status.markSessionReady();
            }
            status.markFrameIgnored();
            return AgentBusFrameProcessResult.ignored();
        }
        if (!properties.getCapture().isEnabled()) {
            status.markFrameIgnored();
            return AgentBusFrameProcessResult.ignored();
        }
        try {
            String hotelId = hotelContextService.resolveSystemHotelId();
            CaptureSourceMessageCommand command = sourceMessageAdapter.toCaptureCommand(
                    hotelId,
                    frame);
            SourceMessageCaptureResult result = captureService.capture(command);
            status.markFrameCaptured();
            return AgentBusFrameProcessResult.captured(result.inboxId(), result.captureStatus());
        } catch (RuntimeException exception) {
            status.markFrameFailed(CAPTURE_FAILED, "AgentBus frame capture failed.");
            return AgentBusFrameProcessResult.failed(CAPTURE_FAILED);
        }
    }

    /**
     * 解析 AgentBus JSON frame。解析失败只记录安全错误代码，不回显原始报文。
     */
    private JsonNode parse(String rawFrame) {
        try {
            return objectMapper.readTree(rawFrame);
        } catch (JsonProcessingException exception) {
            status.markFrameFailed(INVALID_JSON, "AgentBus frame is not valid JSON.");
            return null;
        }
    }

    /**
     * 从两个候选字段中读取第一个非空文本。
     */
    private String firstText(JsonNode firstNode, String firstField, JsonNode secondNode, String secondField) {
        String firstValue = text(firstNode, firstField);
        if (firstValue != null) {
            return firstValue;
        }
        return text(secondNode, secondField);
    }

    /**
     * 读取并清理 JSON 文本字段，空白字符串按缺失处理。
     */
    private String text(JsonNode node, String fieldName) {
        if (node == null || node.path(fieldName).isMissingNode() || node.path(fieldName).isNull()) {
            return null;
        }
        String value = node.path(fieldName).asText();
        String trimmed = value == null ? "" : value.trim();
        return trimmed.isEmpty() ? null : trimmed;
    }
}
