<?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\Entity\EntityTypeManagerInterface;
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;

/**
 * Plugin per testare le API tramite ai_agents.
 */
#[FunctionCall(
  id: 'api_monitor_ai:api_tester_tool',
  function_name: 'api_monitor_ai_api_tester_tool',
  name: 'API Tester',
  description: 'Esegue un test reale su un endpoint specifico usando il suo ID.',
  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 da testare (es. api_order_clients)"),
      required: TRUE,
    ),
    'provider_id' => new ContextDefinition(
      data_type: 'string',
      label: new TranslatableMarkup("Provider ID"),
      description: new TranslatableMarkup("L'ID del provider dell'API."),
      required: FALSE,
    ),
  ],
)]
class ApiTesterTool extends FunctionCallBase implements ExecutableFunctionCallInterface {

  protected ApiSnifferService $apiSniffer;

  protected AiAssistantService $aiAssistantService;

  protected EntityTypeManagerInterface $entityTypeManager;

  /**
   * {@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->entityTypeManager = $container->get('entity_type.manager');
    return $instance;
  }

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

    // Prendiamo le info PUNTUALI solo per questa API
    $apiDetail = $this->aiAssistantService->getCleanDiscovery($api_id, $provider_id);

    if (empty($apiDetail)) {
      $this->setOutput(json_encode([
        'status' => 'error',
        'message' => "API con ID '$api_id' non trovata nel Discovery.",
      ]));
      return;
    }

    $api = reset($apiDetail);
    $response = NULL;
    // Se abbiamo il provider_id, carichiamo il provider e eseguiamo la chiamata.
    if (!empty($api['provider_id'])) {
      /** @var \Drupal\api_monitor_client\Entity\ApiMonitorProvider $provider */
      $provider = $this->entityTypeManager->getStorage('api_monitor_provider')
        ->load($api['provider_id']);
      if ($provider) {
        $response = $this->apiSniffer->call($api, $provider);
      }
    }

    if ($response) {
      $body = $response->getBody()->getContents();
      $status_code = $response->getStatusCode();

      // Cerchiamo se esiste un plugin per questo endpoint per vedere se le PII sono autorizzate
      $isPiiAuthorized = FALSE;
      $probes = $this->apiSniffer->getProbeManager()->getDefinitions();
      foreach ($probes as $plugin_id => $definition) {
        if ($definition['endpoint_id'] === $api_id) {
          $probe_instance = $this->apiSniffer->getProbeManager()->createInstance($plugin_id);
          if ($probe_instance) {
            $isPiiAuthorized = $probe_instance->isPiiAuthorized();
          }
          break;
        }
      }

      // Eseguiamo l'analisi euristica anche per il test manuale
      $analysis = $this->aiAssistantService->analyzeResponseHealth($api_id, $body, $status_code, $isPiiAuthorized);

      $this->setOutput(json_encode([

        'status' => 'success',
        'status_code' => $status_code,
        'test_results' => $body,
        'ai_heuristic_analysis' => !isset($analysis['error']) ? $analysis : 'Analysis failed',
      ]));
    }
    else {
      $this->setOutput(json_encode([
        'status' => 'error',
        'message' => "Impossibile eseguire la chiamata all'API.",
      ]));
    }
  }

}
