#pragma once

#include "MCPTypes.hpp"
#include "../llm/ToolRegistry.hpp"

#include <spdlog/spdlog.h>
#include <nlohmann/json.hpp>

#include <thread>
#include <atomic>
#include <functional>
#include <string>

namespace celuna::mcp {

using json = nlohmann::json;

/**
 * @brief MCP Server - Exposes AISSIA tools via MCP protocol
 *
 * Allows external clients (like Claude Code) to connect to AISSIA
 * and use its tools via JSON-RPC over stdio.
 *
 * Usage:
 *   MCPServer server(toolRegistry);
 *   server.setServerInfo("aissia", "1.0.0");
 *   server.run();  // Blocking - reads stdin, writes stdout
 *
 * Or in a thread:
 *   std::thread serverThread([&]() { server.run(); });
 */
class MCPServer {
public:
    explicit MCPServer(celuna::ToolRegistry& registry);
    ~MCPServer();

    // Server configuration
    void setServerInfo(const std::string& name, const std::string& version);
    void setCapabilities(const json& capabilities);

    // Run the server (blocking)
    void run();

    // Stop the server
    void stop();

    // Check if running
    bool isRunning() const { return m_running; }

private:
    // JSON-RPC handling
    void processLine(const std::string& line);
    json handleRequest(const JsonRpcRequest& request);

    // MCP method handlers
    json handleInitialize(const json& params);
    json handleToolsList(const json& params);
    json handleToolsCall(const json& params);
    json handlePing(const json& params);

    // IO
    std::string readLine();
    void writeLine(const std::string& line);
    void sendResponse(int id, const json& result);
    void sendError(int id, int code, const std::string& message);
    void sendNotification(const std::string& method, const json& params = json::object());

    // State
    celuna::ToolRegistry& m_registry;
    std::atomic<bool> m_running{false};
    bool m_initialized{false};

    // Server info
    std::string m_serverName{"aissia"};
    std::string m_serverVersion{"1.0.0"};
    json m_capabilities;

    // Client info (from initialize)
    std::string m_clientName;
    std::string m_clientVersion;

    std::shared_ptr<spdlog::logger> m_logger;
};

} // namespace celuna::mcp
