package cn.nianxx.thhotel.integrations.mcp.superagent.control;

import cn.nianxx.thhotel.integrations.mcp.superagent.common.request.SuperAgentMcpJsonRpcRequest;
import cn.nianxx.thhotel.integrations.mcp.superagent.common.result.SuperAgentMcpJsonRpcResponse;
import cn.nianxx.thhotel.integrations.mcp.superagent.service.SuperAgentMcpService;
import cn.nianxx.thhotel.integrations.mcp.superagent.service.impl.SuperAgentMcpProperties;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RestController;

/**
 * SuperAgent 内嵌 MCP endpoint。只处理 MCP 鉴权、JSON-RPC 解析和服务分发。
 */
@RestController
@ConditionalOnProperty(prefix = "mcp", name = "enabled", havingValue = "true")
public class SuperAgentMcpController {

    private static final String BEARER_PREFIX = "Bearer ";

    private final SuperAgentMcpService mcpService;
    private final SuperAgentMcpProperties properties;
    private final ObjectMapper objectMapper;

    /**
     * 注入 MCP 服务、配置和 JSON 解析器。
     */
    public SuperAgentMcpController(
            SuperAgentMcpService mcpService,
            SuperAgentMcpProperties properties,
            ObjectMapper objectMapper) {
        this.mcpService = mcpService;
        this.properties = properties;
        this.objectMapper = objectMapper;
    }

    /**
     * MCP HTTP 入口。当前实现支持单个 JSON-RPC 请求。
     */
    @PostMapping(
            value = "${mcp.http-path:/mcp}",
            consumes = MediaType.APPLICATION_JSON_VALUE,
            produces = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<SuperAgentMcpJsonRpcResponse> handle(
            @RequestBody(required = false) String rawBody,
            @RequestHeader(value = "Authorization", required = false) String authorization) {
        String requestBody = rawBody == null ? "" : rawBody;
        ResponseEntity<SuperAgentMcpJsonRpcResponse> bodyLimitFailure = rejectBodyWhenTooLarge(requestBody);
        if (bodyLimitFailure != null) {
            return bodyLimitFailure;
        }
        if (!validAuthorization(authorization)) {
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
                    .body(SuperAgentMcpJsonRpcResponse.error(
                            null,
                            -32001,
                            "MCP_AUTH_INVALID",
                            "MCP 鉴权失败。"));
        }
        SuperAgentMcpJsonRpcRequest request = readRequest(requestBody);
        SuperAgentMcpJsonRpcResponse response = mcpService.handle(request);
        if (response == null) {
            return ResponseEntity.accepted().build();
        }
        return ResponseEntity.ok(response);
    }

    /**
     * 校验 SuperAgent 到 MCP endpoint 的 Bearer token。
     */
    private boolean validAuthorization(String authorization) {
        String authToken = properties.getAuthToken();
        if (!StringUtils.hasText(authToken) || !StringUtils.hasText(authorization)) {
            return false;
        }
        String expected = BEARER_PREFIX + authToken;
        return MessageDigest.isEqual(
                expected.getBytes(StandardCharsets.UTF_8),
                authorization.getBytes(StandardCharsets.UTF_8));
    }

    /**
     * 限制 MCP 请求体大小，避免 SuperAgent 外部输入占用过多后端资源。
     */
    private ResponseEntity<SuperAgentMcpJsonRpcResponse> rejectBodyWhenTooLarge(String rawBody) {
        long maxBodyBytes = properties.getMaxBodyBytes();
        int actualBytes = rawBody.getBytes(StandardCharsets.UTF_8).length;
        if (maxBodyBytes >= 0 && actualBytes > maxBodyBytes) {
            return ResponseEntity.status(HttpStatus.PAYLOAD_TOO_LARGE)
                    .body(SuperAgentMcpJsonRpcResponse.error(
                            null,
                            -32002,
                            "MCP_REQUEST_BODY_TOO_LARGE",
                            "MCP 请求体超过允许大小。"));
        }
        return null;
    }

    /**
     * 解析 JSON-RPC 请求体。
     */
    private SuperAgentMcpJsonRpcRequest readRequest(String rawBody) {
        try {
            return objectMapper.readValue(rawBody, SuperAgentMcpJsonRpcRequest.class);
        } catch (JsonProcessingException exception) {
            throw new SuperAgentMcpRequestException();
        }
    }

    /**
     * 将 MCP JSON 解析错误转换为稳定 JSON-RPC parse error。
     */
    @ExceptionHandler(SuperAgentMcpRequestException.class)
    public ResponseEntity<SuperAgentMcpJsonRpcResponse> handleRequestException() {
        return ResponseEntity.badRequest()
                .body(SuperAgentMcpJsonRpcResponse.error(
                        null,
                        -32700,
                        "MCP_REQUEST_INVALID",
                        "MCP 请求 JSON 不合法。"));
    }

    /**
     * MCP 请求 JSON 不合法时使用稳定异常，交给本 Controller 内部 advice 转换。
     */
    private static class SuperAgentMcpRequestException extends RuntimeException {
    }
}
