package com.correx.infrastructure.tools.mcp

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.JsonObject

/**
 * Minimal JSON-RPC 2.0 + MCP wire types — just the tools slice Correx needs to mount an MCP
 * server's tools as Correx tools. Resources, prompts, and sampling are intentionally absent (nothing
 * consumes them yet). `ignoreUnknownKeys` on the codec lets servers send richer objects than these.
 */
@Serializable
internal data class JsonRpcRequest(
    val method: String,
    val params: JsonElement? = null,
    val id: Long,
    val jsonrpc: String = "2.0",
)

@Serializable
internal data class JsonRpcNotification(
    val method: String,
    val params: JsonElement? = null,
    val jsonrpc: String = "2.0",
)

@Serializable
internal data class JsonRpcResponse(
    val id: Long? = null,
    val result: JsonElement? = null,
    val error: JsonRpcError? = null,
    val jsonrpc: String = "2.0",
)

@Serializable
internal data class JsonRpcError(
    val code: Int,
    val message: String,
    val data: JsonElement? = null,
)

/** One tool advertised by an MCP server (`tools/list` entry). */
@Serializable
internal data class McpToolDescriptor(
    val name: String,
    val description: String = "",
    val inputSchema: JsonObject = JsonObject(emptyMap()),
)

@Serializable
internal data class McpListToolsResult(val tools: List<McpToolDescriptor> = emptyList())

/** One content block of a `tools/call` result. Only text blocks are surfaced to the model. */
@Serializable
internal data class McpContentBlock(
    val type: String,
    val text: String? = null,
)

@Serializable
internal data class McpCallToolResult(
    val content: List<McpContentBlock> = emptyList(),
    @SerialName("isError") val isError: Boolean = false,
) {
    /** Flatten text blocks into the single string the Correx tool contract returns. */
    fun text(): String = content.mapNotNull { it.text }.joinToString("\n")
}
