<?php

declare(strict_types=1);

namespace Drupal\api_monitor_ai\Plugin\AiFunctionCall;

use Drupal\api_monitor_ai\AiAssistantService;
use Drupal\api_monitor_client\ApiSnifferService;
use Drupal\Core\Plugin\Context\ContextDefinition;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\ai\Attribute\FunctionCall;
use Drupal\ai\Base\FunctionCallBase;
use Drupal\ai\Service\FunctionCalling\ExecutableFunctionCallInterface;
use Drupal\ai\Service\FunctionCalling\FunctionCallInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Yaml\Yaml;

/**
 * Tool per generare snippet di codice client per le API.
 */
#[FunctionCall(
  id: 'api_monitor_ai:generate_api_client',
  function_name: 'api_monitor_ai_generate_api_client',
  name: 'Generate API Client',
  description: 'Ottiene le specifiche tecniche di un endpoint per generare snippet di codice (React, PHP, Python, ecc.)',
  group: 'information_tools',
  context_definitions: [
    'api_id' => new ContextDefinition(
      data_type: 'string',
      label: new TranslatableMarkup("API ID"),
      description: new TranslatableMarkup("L'ID univoco dell'API per cui generare il codice."),
      required: TRUE,
    ),
    'language' => new ContextDefinition(
      data_type: 'string',
      label: new TranslatableMarkup("Linguaggio o Framework"),
      description: new TranslatableMarkup("Il linguaggio o framework richiesto (es. React, PHP, Python)."),
      required: FALSE,
    ),
    'provider_id' => new ContextDefinition(
      data_type: 'string',
      label: new TranslatableMarkup("Provider ID"),
      description: new TranslatableMarkup("L'ID del provider dell'API."),
      required: FALSE,
    ),
  ],
)]
class GenerateApiClientTool extends FunctionCallBase implements ExecutableFunctionCallInterface {

  protected ApiSnifferService $apiSniffer;
  protected AiAssistantService $aiAssistantService;
  protected $probeManager;

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition): FunctionCallInterface|static {
    $instance = new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get('ai.context_definition_normalizer'),
    );
    $instance->apiSniffer = $container->get('api_monitor_client.sniffer');
    $instance->aiAssistantService = $container->get('api_monitor_ai.assistance_service');
    $instance->probeManager = $container->get('plugin.manager.api_monitor_probe');
    return $instance;
  }

  /**
   * {@inheritdoc}
   */
  public function execute() {
    $api_id = $this->getContextValue('api_id');
    $provider_id = $this->getContextValue('provider_id');
    $language = $this->getContextValue('language') ?? 'Generic';

    // Recuperiamo i dati dell'API tramite il metodo di pulizia centralizzato
    $api_details = $this->aiAssistantService->getCleanDiscovery($api_id, $provider_id);
    $api_data = reset($api_details);

    if (!$api_data) {
      $this->setOutput(json_encode(['error' => "API '$api_id' non trovata."]));
      return;
    }

    // Cerchiamo se esiste un probe specifico per questo endpoint per recuperare il payload
    $payload = [];

    $probes = $this->probeManager->getDefinitions();
    foreach ($probes as $plugin_id => $definition) {
      if ($definition['endpoint_id'] === $api_id) {
        $probe_instance = $this->probeManager->createInstance($plugin_id);
        if ($probe_instance) {
          $payload = $probe_instance->getPayload();
        }
        break;
      }
    }

    // Restituiamo i dettagli tecnici che serviranno all'IA per scrivere il codice
    $this->setOutput(json_encode([
      'api_info' => [
        'id' => $api_data['id'],
        'path' => $api_data['path'],
        'method' => $api_data['methods'] ?? ['GET'],
        'parameters' => $api_data['parameters'] ?? [],
        'headers' => $api_data['headers'] ?? [],
        'payload_example' => $payload,
      ],
      'requested_language' => $language,
    ]));
  }
}
