<?php

declare(strict_types=1);

namespace Drupal\Tests\ai_ckeditor\Kernel;

use Drupal\ai\Event\PreGenerateResponseEvent;
use Drupal\ai\OperationType\Chat\ChatInput;
use Drupal\ai\OperationType\Chat\ChatMessage;
use Drupal\KernelTests\KernelTestBase;
use PHPUnit\Framework\Attributes\RunTestsInSeparateProcesses;

/**
 * Proves entity context set on ChatInput reaches event subscribers.
 *
 * The ai_ckeditor controller sets entity context on ChatInput via
 * $input->setRequestMetadataValue('entity_context', [...]). ProviderProxy seeds
 * PreGenerateResponseEvent from $input->getAllRequestMetadata() so any
 * subscriber (notably ai_context) can read the entity scope from
 * $event->getMetadata('entity_context') without needing a custom event.
 *
 * @group ai_ckeditor
 */
#[RunTestsInSeparateProcesses]
class EntityContextMetadataTest extends KernelTestBase {

  /**
   * {@inheritdoc}
   */
  protected static $modules = [
    'system',
    'user',
    'filter',
    'editor',
    'ckeditor5',
    'ai',
    'ai_ckeditor',
  ];

  /**
   * Entity context set on ChatInput must be visible to event subscribers.
   */
  public function testEntityContextMetadataReachesEventSubscribers(): void {
    $captured = [];

    $dispatcher = $this->container->get('event_dispatcher');
    $dispatcher->addListener(
      PreGenerateResponseEvent::EVENT_NAME,
      function (PreGenerateResponseEvent $event) use (&$captured) {
        if (!in_array('ai_ckeditor', $event->getTags(), TRUE)) {
          return;
        }
        $captured = $event->getMetadata('entity_context') ?? [];
      }
    );

    $input = new ChatInput([
      new ChatMessage('user', 'Rewrite this sentence.'),
    ]);
    $input->setSystemPrompt('You are a helpful assistant.');
    $input->setRequestMetadataValue('entity_context', [
      'entity_type' => 'node',
      'bundle' => 'blog_post',
      'id' => '42',
    ]);

    // Dispatch the event the same way ProviderProxy::wrapperCall() does
    // after the metadata plumbing change: pass the input request metadata
    // as the event's metadata seed.
    $event = new PreGenerateResponseEvent(
      requestThreadId: 'test-thread-id',
      providerId: 'test_provider',
      operationType: 'chat',
      configuration: [],
      input: $input,
      modelId: 'test-model',
      tags: ['chat', 'ai_ckeditor'],
      debugData: [],
      metadata: $input->getAllRequestMetadata(),
    );
    $dispatcher->dispatch($event, PreGenerateResponseEvent::EVENT_NAME);

    $this->assertSame('node', $captured['entity_type'] ?? NULL);
    $this->assertSame('blog_post', $captured['bundle'] ?? NULL);
    $this->assertSame('42', $captured['id'] ?? NULL);
  }

  /**
   * Requests without entity context must not expose stale metadata.
   */
  public function testNoMetadataWhenInputHasNoEntityContext(): void {
    $captured = 'not-run';

    $dispatcher = $this->container->get('event_dispatcher');
    $dispatcher->addListener(
      PreGenerateResponseEvent::EVENT_NAME,
      function (PreGenerateResponseEvent $event) use (&$captured) {
        if (!in_array('ai_ckeditor', $event->getTags(), TRUE)) {
          return;
        }
        $captured = $event->getMetadata('entity_context');
      }
    );

    $input = new ChatInput([
      new ChatMessage('user', 'Generic request.'),
    ]);

    $event = new PreGenerateResponseEvent(
      requestThreadId: 'test-thread-id',
      providerId: 'test_provider',
      operationType: 'chat',
      configuration: [],
      input: $input,
      modelId: 'test-model',
      tags: ['chat', 'ai_ckeditor'],
      debugData: [],
      metadata: $input->getAllRequestMetadata(),
    );
    $dispatcher->dispatch($event, PreGenerateResponseEvent::EVENT_NAME);

    $this->assertNull($captured);
  }

}
