<?php

/**
 * MCP Name Sanitizer utility for normalizing component names.
 *
 * @package McpAdapter
 */
declare (strict_types=1);
namespace PYS_PRO_GLOBAL\WP\MCP\Domain\Utils;

use WP_Error;
/**
 * Utility class for sanitizing names to MCP-valid format.
 *
 * Implements best-effort sanitization per MCP 2025-11-25 spec:
 * - Length: 1-128 characters
 * - Charset: A-Za-z0-9_.-
 *
 * Used for both tools and prompts (same naming rules).
 * NOT used for resources (which use URIs as identifiers).
 *
 * @since 0.5.0
 */
class McpNameSanitizer
{
    /**
     * Maximum length for MCP tool/prompt names per spec.
     *
     * @var int
     */
    public const MAX_LENGTH = 128;
    /**
     * Length of the hash suffix used for truncation uniqueness.
     *
     * @var int
     */
    public const HASH_LENGTH = 12;
    /**
     * Maximum characters to keep when truncating (MAX_LENGTH - 1 separator - HASH_LENGTH).
     *
     * @var int
     */
    public const TRUNCATE_LENGTH = 115;
    /**
     * Sanitize a name to be MCP-valid for tools and prompts.
     *
     * Normalization steps:
     * 1. Trim whitespace
     * 2. Replace `/` with `-` (forward slash not allowed in MCP)
     * 3. If valid, return as-is
     * 4. Otherwise: transliterate accents, replace invalid chars, collapse hyphens, trim edges
     * 5. If too long: truncate + add hash suffix for uniqueness
     * 6. If still invalid/empty: return WP_Error
     *
     * @param string $name Original name.
     *
     * @return string|\WP_Error Sanitized name or WP_Error if unsalvageable.
     * @since 0.5.0
     *
     */
    public static function sanitize_name(string $name)
    {
        $original = $name;
        // Step 1: Trim whitespace.
        $name = trim($name);
        // Step 2: Replace / with - (forward slash not allowed in MCP).
        $name = str_replace('/', '-', $name);
        // Step 3: Early validation - if already valid, return as-is.
        if (McpValidator::validate_name($name)) {
            return $name;
        }
        // Step 4a: Transliterate accented characters to ASCII equivalents.
        // Uses WordPress core function: é→e, ü→u, ñ→n, etc.
        $name = remove_accents($name);
        // Step 4b: Replace any remaining non-allowed chars with hyphen.
        $name = (string) preg_replace('/[^a-zA-Z0-9_.-]/', '-', $name);
        // Step 4c: Collapse consecutive hyphens.
        $name = (string) preg_replace('/-+/', '-', $name);
        // Step 4d: Trim leading/trailing hyphens and underscores.
        $name = trim($name, '-_');
        // Step 5: Handle length > 128.
        if (strlen($name) > self::MAX_LENGTH) {
            $hash = substr(md5($original), 0, self::HASH_LENGTH);
            $name = substr($name, 0, self::TRUNCATE_LENGTH) . '-' . $hash;
        }
        // Step 6: Final check - only empty is possible failure after sanitization.
        // Characters are guaranteed valid (replaced), length is handled (truncated).
        if (empty($name)) {
            return new WP_Error('mcp_name_invalid', sprintf(
                /* translators: %s: original ability name */
                __('Unable to derive valid MCP name from: %s', 'mcp-adapter'),
                $original
            ));
        }
        return $name;
    }
}
