<?php

declare(strict_types=1);

namespace KimaAI\Ai;

defined('ABSPATH') || exit;

final class ToolRegistry {

  /**
   * Single source of truth for tool definitions.
   * These are “tool specs”, not “premium gating”.
   */
  public static function builtin(): array {
    $tools = [
      'wp_get_post' => [
        'label' => 'wp_get_post',
        'description' => 'Fetch a WordPress post by ID.',
        'parameters' => [
          'type' => 'object',
          'properties' => [
            'id' => [
              'type' => 'integer',
              'description' => 'The post ID',
            ],
          ],
          'required' => ['id'],
          'additionalProperties' => false,
        ],
      ],

      'wp_search_posts' => [
        'label' => 'wp_search_posts',
        'description' => 'Search public posts by keyword.',
        'parameters' => [
          'type' => 'object',
          'properties' => [
            'q' => [
              'type' => 'string',
              'description' => 'Search query',
            ],
            'limit' => [
              'type' => 'integer',
              'minimum' => 1,
              'maximum' => 25,
            ],
          ],
          'required' => ['q'],
          'additionalProperties' => false,
        ],
      ],

      'kb_vector_search' => [
        'label' => 'kb_vector_search',
        'description' => 'Search the website knowledge base using semantic (vector) search.',
        'hidden' => true,
        'parameters' => [
          'type' => 'object',
          'properties' => [
            'query' => [
              'type' => 'string',
              'description' => 'Natural language question or search query.',
            ],
            'top_k' => [
              'type' => 'integer',
              'minimum' => 1,
              'maximum' => 10,
            ],
            'min_score' => [
              'type' => 'number',
              'minimum' => 0,
              'maximum' => 1,
            ],
          ],
          'required' => ['query'],
          'additionalProperties' => false,
        ],
      ],
    ];

    $tools = apply_filters('kimaai_tools_registry', $tools);
    return self::sanitize($tools);
  }

  /**
   * Returns OpenAI “tools” payload (Responses API style).
   */
  public static function asAiProviderTools(): array {
    $out = [];
    foreach (self::builtin() as $name => $tool) {
      $out[] = [
        'type' => 'function',
        'name' => $name,
        'description' => (string) ($tool['description'] ?? ''),
        'parameters' => $tool['parameters'] ?? [
          'type' => 'object',
          'properties' => new \stdClass(),
        ],
      ];
    }
    return $out;
  }

  /**
   * Returns admin checkbox options (Free UI + Pro UI).
   */
  public static function asSelectOptions(): array {
    $opts = [];
    foreach (self::builtin() as $name => $tool) {
      if ($tool['hidden']) {
        continue;
      }
      $label = $tool['label'];
      $desc = $tool['description'];
      $opts[] = [
        'value' => $name,
        'label' => $label . ($desc ? ' - ' . $desc : ''),
      ];
    }
    return $opts;
  }

  /**
   * Get a single registered tool by name.
   */
  public static function get(string $name): ?array {
    $all = self::builtin();
    return $all[$name] ?? null;
  }

  /**
   * Normalize third-party registry definitions.
   */
  private static function sanitize($tools): array {
    if (!is_array($tools)) {
      return [];
    }

    $out = [];
    foreach ($tools as $name => $tool) {
      $name = is_string($name) ? $name : '';
      if (!preg_match('/^[A-Za-z_][A-Za-z0-9_]{0,63}$/', $name)) {
        continue;
      }
      if (!is_array($tool)) {
        continue;
      }

      $out[$name] = [
        'label' => (string) ($tool['label'] ?? $name),
        'description' => (string) ($tool['description'] ?? ''),
        'hidden' => !empty($tool['hidden']),
        'parameters' => is_array($tool['parameters'] ?? null) ? $tool['parameters'] : [
          'type' => 'object',
          'properties' => new \stdClass(),
          'additionalProperties' => false,
        ],
        // callback can be callable or "function_name"
        'callback' => $tool['callback'] ?? null,
      ];
    }
    return $out;
  }
}
