use serde_json::{Value, json};

#[derive(Debug, Clone)]
pub(super) struct JsonRpcError {
    pub code: i64,
    pub message: String,
}

impl JsonRpcError {
    pub fn new(code: i64, message: impl Into<String>) -> Self {
        Self {
            code,
            message: message.into(),
        }
    }

    pub fn with_id(self, id: Value) -> Value {
        jsonrpc_error(id, self.code, self.message)
    }
}

pub(super) fn jsonrpc_result(id: Value, result: Value) -> Value {
    json!({
        "jsonrpc": "2.0",
        "id": id,
        "result": result
    })
}

pub(super) fn is_successful_tool_response(response: &Value) -> bool {
    response
        .get("result")
        .and_then(|r| r.get("isError"))
        .and_then(Value::as_bool)
        == Some(false)
}

pub(super) fn jsonrpc_error(id: Value, code: i64, message: impl Into<String>) -> Value {
    json!({
        "jsonrpc": "2.0",
        "id": id,
        "error": {
            "code": code,
            "message": message.into()
        }
    })
}

pub(super) fn tool_success(text: &str, structured_content: Value) -> Value {
    json!({
        "content": [{ "type": "text", "text": text }],
        "structuredContent": structured_content,
        "isError": false
    })
}

pub(super) fn tool_failure(text: &str, structured_content: Value) -> Value {
    json!({
        "content": [{ "type": "text", "text": text }],
        "structuredContent": structured_content,
        "isError": true
    })
}

pub(super) fn tool_runtime_error(error: anyhow::Error) -> JsonRpcError {
    JsonRpcError::new(-32603, format!("{error:#}"))
}
