<?php

declare(strict_types=1);

namespace Drupal\ai_test\Plugin\AiPlatform;

use Drupal\ai\Attribute\AiPlatform;
use Drupal\ai\Plugin\AiPlatform\AiPlatformPluginBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Symfony\AI\Platform\Message\MessageBag;
use Symfony\AI\Platform\Model;
use Symfony\AI\Platform\PlatformInterface;
use Symfony\AI\Platform\Result\StreamResult;
use Symfony\AI\Platform\Result\TextResult;
use Symfony\AI\Platform\Result\ToolCall;
use Symfony\AI\Platform\Result\ToolCallResult;
use Symfony\AI\Platform\Bridge\Generic\CompletionsModel;
use Symfony\AI\Platform\Bridge\Generic\ModelCatalog;
use Symfony\AI\Platform\Capability;
use Symfony\AI\Platform\ModelCatalog\ModelCatalogInterface;
use Symfony\AI\Platform\Test\InMemoryPlatform;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Echo platform plugin for testing using Symfony AI InMemoryPlatform.
 */
#[AiPlatform(
  id: 'echo',
  label: new TranslatableMarkup('Echo'),
  description: new TranslatableMarkup('Echo platform for testing.'),
)]
final class EchoAiPlatform extends AiPlatformPluginBase {

  /**
   * Provider id of the test fixture, ready to pass to AI APIs.
   *
   * Tests should use this constant rather than hard-coding the value, so the
   * same test code keeps working if the underlying provider id changes (e.g.
   * when porting between branches that wrap the test platform differently).
   *
   * @see config/install/ai.platform.echo_test.yml
   */
  public const TEST_PROVIDER_ID = 'ai_platform:echo_test';

  /**
   * A model id provided by this test platform's catalog.
   */
  public const TEST_MODEL_ID = 'gpt-test';

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition): static {
    // Skip parent::create() which requires HttpClientInterface — not needed
    // for InMemoryPlatform.
    return new static($configuration, $plugin_id, $plugin_definition);
  }

  /**
   * {@inheritdoc}
   */
  protected function initializePlatform(): PlatformInterface {
    return new InMemoryPlatform(function (Model $model, object $input, array $options) {
      // Check if tools are requested — simulate a tool call response.
      if (!empty($options['tools'])) {
        $tool = reset($options['tools']);
        return new ToolCallResult(
          new ToolCall('call_test_123', $tool->getName(), ['arg1' => 'value1'])
        );
      }

      // Build a deterministic echo response matching the old EchoProvider
      // format for backward compatibility with existing tests.
      $input_text = '';
      if ($input instanceof MessageBag) {
        $userMessage = $input->getUserMessage();
        if ($userMessage) {
          $input_text = $userMessage->asText() ?? '';
        }
      }
      $text = sprintf('Hello world! Input: %s. Config: [].', $input_text);

      // Return a StreamResult when streaming is requested.
      if (!empty($options['stream'])) {
        $generator = (function () use ($text) {
          yield $text;
        })();
        return new StreamResult($generator);
      }

      return new TextResult($text);
    });
  }

  /**
   * {@inheritdoc}
   */
  public function getModelCatalog(): ModelCatalogInterface {
    $capabilities = [
      Capability::INPUT_MESSAGES,
      Capability::INPUT_TEXT,
      Capability::OUTPUT_TEXT,
      Capability::OUTPUT_STREAMING,
    ];
    return new ModelCatalog([
      'gpt-test' => [
        'class' => CompletionsModel::class,
        'capabilities' => $capabilities,
      ],
      'gpt-awesome' => [
        'class' => CompletionsModel::class,
        'capabilities' => $capabilities,
      ],
    ]);
  }

  /**
   * {@inheritdoc}
   */
  public function getAvailableConfiguration(string $operation_type, string $model_id): array {
    if ($operation_type === 'chat') {
      return [
        'max_tokens' => [
          'label' => 'Max Tokens',
          'description' => 'The maximum number of tokens that can be generated in the chat completion.',
          'type' => 'integer',
          'default' => 4096,
          'required' => FALSE,
          'constraints' => [
            'min' => 0,
            'max' => 4096,
          ],
        ],
        'temperature' => [
          'label' => 'Temperature',
          'description' => 'Sampling temperature 0-1. Higher values mean more random output.',
          'type' => 'float',
          'default' => 1,
          'required' => FALSE,
          'constraints' => [
            'min' => 0,
            'max' => 2,
            'step' => 0.1,
          ],
        ],
      ];
    }
    return [];
  }

  /**
   * {@inheritdoc}
   */
  public function buildConfigurationForm(array $form, FormStateInterface $form_state): array {
    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function validateConfigurationForm(array &$form, FormStateInterface $form_state): void {
  }

  /**
   * {@inheritdoc}
   */
  public function submitConfigurationForm(array &$form, FormStateInterface $form_state): void {
  }

}
