import { DEBUG_BUILD } from '../../debug-build.js';
import { debug } from '../../utils/debug-logger.js';
import { fill } from '../../utils/object.js';
import { captureError } from './errorCapture.js';

/**
 * Handler method wrapping for MCP server instrumentation
 *
 * Provides automatic error capture and span correlation for tool, resource,
 * and prompt handlers.
 */


/**
 * Generic function to wrap MCP server method handlers
 * @internal
 * @param serverInstance - MCP server instance
 * @param methodName - Method name to wrap (tool, resource, prompt)
 */
function wrapMethodHandler(serverInstance, methodName) {
  fill(serverInstance, methodName, originalMethod => {
    return function ( name, ...args) {
      const handler = args[args.length - 1];

      if (typeof handler !== 'function') {
        return (originalMethod ).call(this, name, ...args);
      }

      const wrappedHandler = createWrappedHandler(handler , methodName, name);
      return (originalMethod ).call(this, name, ...args.slice(0, -1), wrappedHandler);
    };
  });
}

/**
 * Creates a wrapped handler with span correlation and error capture
 * @internal
 * @param originalHandler - Original handler function
 * @param methodName - MCP method name
 * @param handlerName - Handler identifier
 * @returns Wrapped handler function
 */
function createWrappedHandler(originalHandler, methodName, handlerName) {
  return function ( ...handlerArgs) {
    try {
      return createErrorCapturingHandler.call(this, originalHandler, methodName, handlerName, handlerArgs);
    } catch (error) {
      DEBUG_BUILD && debug.warn('MCP handler wrapping failed:', error);
      return originalHandler.apply(this, handlerArgs);
    }
  };
}

/**
 * Creates an error-capturing wrapper for handler execution
 * @internal
 * @param originalHandler - Original handler function
 * @param methodName - MCP method name
 * @param handlerName - Handler identifier
 * @param handlerArgs - Handler arguments
 * @param extraHandlerData - Additional handler context
 * @returns Handler execution result
 */
function createErrorCapturingHandler(

  originalHandler,
  methodName,
  handlerName,
  handlerArgs,
) {
  try {
    const result = originalHandler.apply(this, handlerArgs);

    if (result && typeof result === 'object' && typeof (result ).then === 'function') {
      return Promise.resolve(result).catch(error => {
        captureHandlerError(error, methodName, handlerName);
        throw error;
      });
    }

    return result;
  } catch (error) {
    captureHandlerError(error , methodName, handlerName);
    throw error;
  }
}

/**
 * Captures handler execution errors based on handler type
 * @internal
 * @param error - Error to capture
 * @param methodName - MCP method name
 * @param handlerName - Handler identifier
 */
function captureHandlerError(error, methodName, handlerName) {
  try {
    const extraData = {};

    if (methodName === 'tool') {
      extraData.tool_name = handlerName;

      if (
        error.name === 'ProtocolValidationError' ||
        error.message.includes('validation') ||
        error.message.includes('protocol')
      ) {
        captureError(error, 'validation', extraData);
      } else if (
        error.name === 'ServerTimeoutError' ||
        error.message.includes('timed out') ||
        error.message.includes('timeout')
      ) {
        captureError(error, 'timeout', extraData);
      } else {
        captureError(error, 'tool_execution', extraData);
      }
    } else if (methodName === 'resource') {
      extraData.resource_uri = handlerName;
      captureError(error, 'resource_execution', extraData);
    } else if (methodName === 'prompt') {
      extraData.prompt_name = handlerName;
      captureError(error, 'prompt_execution', extraData);
    }
  } catch (captureErr) {
    // noop
  }
}

/**
 * Wraps tool handlers to associate them with request spans
 * @param serverInstance - MCP server instance
 */
function wrapToolHandlers(serverInstance) {
  wrapMethodHandler(serverInstance, 'tool');
}

/**
 * Wraps resource handlers to associate them with request spans
 * @param serverInstance - MCP server instance
 */
function wrapResourceHandlers(serverInstance) {
  wrapMethodHandler(serverInstance, 'resource');
}

/**
 * Wraps prompt handlers to associate them with request spans
 * @param serverInstance - MCP server instance
 */
function wrapPromptHandlers(serverInstance) {
  wrapMethodHandler(serverInstance, 'prompt');
}

/**
 * Wraps all MCP handler types (tool, resource, prompt) for span correlation
 * @param serverInstance - MCP server instance
 */
function wrapAllMCPHandlers(serverInstance) {
  wrapToolHandlers(serverInstance);
  wrapResourceHandlers(serverInstance);
  wrapPromptHandlers(serverInstance);
}

export { wrapAllMCPHandlers, wrapPromptHandlers, wrapResourceHandlers, wrapToolHandlers };//# sourceMappingURL=http://go/sourcemap/sourcemaps/fc2563ec93d793fc275eef734405a4fdf8b47b20/node_modules/@sentry/core/build/esm/integrations/mcp-server/handlers.js.map
