#pragma once

#include "MCPTypes.hpp"
#include "MCPTransport.hpp"
#include "StdioTransport.hpp"

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

#include <memory>
#include <map>
#include <vector>
#include <string>

namespace celuna::mcp {

using json = nlohmann::json;

/**
 * @brief Client for managing multiple MCP servers
 *
 * Handles:
 * - Loading server configurations
 * - Starting/stopping servers
 * - Initializing MCP protocol
 * - Discovering and calling tools
 */
class MCPClient {
public:
    MCPClient();
    ~MCPClient();

    /**
     * @brief Load server configurations from JSON file
     * @param configPath Path to mcp.json config file
     * @return true if config loaded successfully
     */
    bool loadConfig(const std::string& configPath);

    /**
     * @brief Connect to all enabled servers
     * @return Number of servers successfully connected
     */
    int connectAll();

    /**
     * @brief Connect to a specific server by name
     * @return true if connected successfully
     */
    bool connect(const std::string& serverName);

    /**
     * @brief Disconnect from a specific server
     */
    void disconnect(const std::string& serverName);

    /**
     * @brief Disconnect from all servers
     */
    void disconnectAll();

    /**
     * @brief List all available tools across all connected servers
     * @return Vector of tools with server prefix (e.g., "filesystem:read_file")
     */
    std::vector<MCPTool> listAllTools();

    /**
     * @brief Call a tool by name
     * @param toolName Full tool name (e.g., "filesystem:read_file")
     * @param arguments Tool arguments
     * @return Tool result
     */
    MCPToolResult callTool(const std::string& toolName, const json& arguments);

    /**
     * @brief Get total number of available tools
     */
    size_t toolCount() const;

    /**
     * @brief Check if a server is connected
     */
    bool isConnected(const std::string& serverName) const;

    /**
     * @brief Get list of connected server names
     */
    std::vector<std::string> getConnectedServers() const;

private:
    struct ConnectedServer {
        MCPServerConfig config;
        std::unique_ptr<IMCPTransport> transport;
        MCPServerInfo info;
        std::vector<MCPTool> tools;
        bool initialized = false;
    };

    std::shared_ptr<spdlog::logger> m_logger;
    std::map<std::string, MCPServerConfig> m_configs;
    std::map<std::string, ConnectedServer> m_servers;

    // MCP protocol methods
    bool initializeServer(ConnectedServer& server);
    bool discoverTools(ConnectedServer& server);
    std::pair<std::string, std::string> parseToolName(const std::string& toolName);
};

} // namespace celuna::mcp
