#ifdef PROXYSQLGENAI

#include "proxysql.h"

#include "../deps/json/json.hpp"
using json = nlohmann::json;
#define PROXYJSON

#include "MCP_Thread.h"
#include "MCP_Tool_Handler.h"
#include "Config_Tool_Handler.h"
#include "proxysql_debug.h"
#include "proxysql_utils.h"

#include <cstring>

Config_Tool_Handler::Config_Tool_Handler(MCP_Threads_Handler* handler)
	: mcp_handler(handler)
{
	pthread_mutex_init(&handler_lock, NULL);
	proxy_debug(PROXY_DEBUG_GENERIC, 3, "Config_Tool_Handler created\n");
}

Config_Tool_Handler::~Config_Tool_Handler() {
	close();
	pthread_mutex_destroy(&handler_lock);
	proxy_debug(PROXY_DEBUG_GENERIC, 3, "Config_Tool_Handler destroyed\n");
}

int Config_Tool_Handler::init() {
	proxy_info("Config_Tool_Handler initialized\n");
	return 0;
}

void Config_Tool_Handler::close() {
	proxy_debug(PROXY_DEBUG_GENERIC, 2, "Config_Tool_Handler closed\n");
}

json Config_Tool_Handler::get_tool_list() {
	json tools = json::array();

	// get_config
	tools.push_back(create_tool_description(
		"get_config",
		"Get the current value of a ProxySQL MCP configuration variable",
		{
			{"type", "object"},
			{"properties", {
				{"variable_name", {
					{"type", "string"},
					{"description", "Variable name (without 'mcp-' prefix)"}
				}}
			}},
			{"required", {"variable_name"}}
		}
	));

	// set_config
	tools.push_back(create_tool_description(
		"set_config",
		"Set the value of a ProxySQL MCP configuration variable",
		{
			{"type", "object"},
			{"properties", {
				{"variable_name", {
					{"type", "string"},
					{"description", "Variable name (without 'mcp-' prefix)"}
				}},
				{"value", {
					{"type", "string"},
					{"description", "New value for the variable"}
				}}
			}},
			{"required", {"variable_name", "value"}}
		}
	));

	// reload_config
	tools.push_back(create_tool_description(
		"reload_config",
		"Reload ProxySQL MCP configuration from disk/memory to runtime",
		{
			{"type", "object"},
			{"properties", {
				{"scope", {
					{"type", "string"},
					{"enum", {"disk", "memory", "runtime"}},
					{"description", "Reload scope: 'disk' (from disk to memory), 'memory' (not applicable), 'runtime' (from memory to runtime)"}
				}}
			}},
			{"required", {"scope"}}
		}
	));

	// list_variables
	tools.push_back(create_tool_description(
		"list_variables",
		"List all ProxySQL MCP configuration variables",
		{
			{"type", "object"},
			{"properties", {
				{"filter", {
					{"type", "string"},
					{"description", "Optional filter pattern (e.g., 'mysql_%' for MySQL-related variables)"}
				}}
			}}
		}
	));

	// get_status
	tools.push_back(create_tool_description(
		"get_status",
		"Get ProxySQL MCP server status information",
		{
			{"type", "object"},
			{"properties", {}}
		}
	));

	json result;
	result["tools"] = tools;
	return result;
}

json Config_Tool_Handler::get_tool_description(const std::string& tool_name) {
	// For now, just return the basic description from the list
	// In a full implementation, this would provide more detailed schema info
	json tools_list = get_tool_list();
	for (const auto& tool : tools_list["tools"]) {
		if (tool["name"] == tool_name) {
			return tool;
		}
	}
	return create_error_response("Tool not found: " + tool_name);
}

json Config_Tool_Handler::execute_tool(const std::string& tool_name, const json& arguments) {
	pthread_mutex_lock(&handler_lock);

	json result;

	try {
		if (tool_name == "get_config") {
			std::string var_name = arguments.value("variable_name", "");
			result = handle_get_config(var_name);
		} else if (tool_name == "set_config") {
			std::string var_name = arguments.value("variable_name", "");
			std::string var_value = arguments.value("value", "");
			result = handle_set_config(var_name, var_value);
		} else if (tool_name == "reload_config") {
			std::string scope = arguments.value("scope", "runtime");
			result = handle_reload_config(scope);
		} else if (tool_name == "list_variables") {
			std::string filter = arguments.value("filter", "");
			result = handle_list_variables(filter);
		} else if (tool_name == "get_status") {
			result = handle_get_status();
		} else {
			result = create_error_response("Unknown tool: " + tool_name);
		}
	} catch (const std::exception& e) {
		result = create_error_response(std::string("Exception: ") + e.what());
	}

	pthread_mutex_unlock(&handler_lock);
	return result;
}

json Config_Tool_Handler::handle_get_config(const std::string& var_name) {
	if (!mcp_handler) {
		return create_error_response("MCP handler not initialized");
	}

	char val[1024];
	if (mcp_handler->get_variable(var_name.c_str(), val) == 0) {
		json result;
		result["variable_name"] = var_name;
		result["value"] = val;
		return create_success_response(result);
	} else {
		return create_error_response("Variable not found: " + var_name);
	}
}

json Config_Tool_Handler::handle_set_config(const std::string& var_name, const std::string& var_value) {
	if (!mcp_handler) {
		return create_error_response("MCP handler not initialized");
	}

	if (mcp_handler->set_variable(var_name.c_str(), var_value.c_str()) == 0) {
		json result;
		result["variable_name"] = var_name;
		result["value"] = var_value;
		result["message"] = "Variable set successfully. Use 'reload_config' to load to runtime.";
		return create_success_response(result);
	} else {
		return create_error_response("Failed to set variable: " + var_name);
	}
}

json Config_Tool_Handler::handle_reload_config(const std::string& scope) {
	if (!mcp_handler) {
		return create_error_response("MCP handler not initialized");
	}

	// This is a stub - actual implementation would call Admin_FlushVariables
	// For now, return success with a message
	json result;
	result["scope"] = scope;
	result["message"] = "Configuration reload functionality to be implemented";
	return create_success_response(result);
}

json Config_Tool_Handler::handle_list_variables(const std::string& filter) {
	if (!mcp_handler) {
		return create_error_response("MCP handler not initialized");
	}

	char** vars = mcp_handler->get_variables_list();
	if (!vars) {
		return create_error_response("Failed to get variables list");
	}

	json variables = json::array();

	// Filter and list variables
	for (int i = 0; vars[i] != NULL; i++) {
		std::string var_name = vars[i];

		// Apply filter if provided
		if (!filter.empty()) {
			// Simple pattern matching (expand to full SQL LIKE pattern later)
			if (var_name.find(filter) == std::string::npos) {
				continue;
			}
		}

		char val[1024];
		if (mcp_handler->get_variable(var_name.c_str(), val) == 0) {
			json var;
			var["name"] = var_name;
			var["value"] = val;
			variables.push_back(var);
		}

		free(vars[i]);
	}
	free(vars);

	json result;
	result["variables"] = variables;
	result["count"] = variables.size();
	return create_success_response(result);
}

json Config_Tool_Handler::handle_get_status() {
	if (!mcp_handler) {
		return create_error_response("MCP handler not initialized");
	}

	json status;
	status["enabled"] = mcp_handler->variables.mcp_enabled;
	status["port"] = mcp_handler->variables.mcp_port;
	status["total_requests"] = mcp_handler->status_variables.total_requests;
	status["failed_requests"] = mcp_handler->status_variables.failed_requests;
	status["active_connections"] = mcp_handler->status_variables.active_connections;

	return create_success_response(status);
}

#endif /* PROXYSQLGENAI */
