<?php

declare(strict_types=1);

namespace Drupal\Tests\conductor\Kernel;

use Drupal\KernelTests\KernelTestBase;
use Drupal\Tests\conductor\Trait\KeyTrait;
use PHPUnit\Framework\Attributes\Group;

/**
 * Tests the ConductorHttpApiClient streaming functionality.
 */
#[Group("conductor")]
final class ConductorHttpApiClientStreamKernelTest extends KernelTestBase {

  use KeyTrait;

  /**
   * {@inheritdoc}
   */
  protected static $modules = [
    'system',
    'key',
    'conductor',
    'conductor_test',
    'http_request_mock',
  ];

  /**
   * {@inheritdoc}
   */
  public function setUp(): void {
    parent::setUp();
    $this->installConfig(['system', 'conductor', 'key']);
    $this->generateKey();
  }

  /**
   * Tests streaming NDJSON response from content-generation endpoint.
   *
   * This test verifies the streaming functionality by directly accessing
   * the PSR-7 response body before it's wrapped in a StreamedResponse,
   * since StreamedResponse clears all output buffers which interferes
   * with test output capturing.
   *
   * @see \Drupal\conductor_test\Plugin\ServiceMock\ApiConductorComPlugin::getResponse()
   */
  public function testStreamingContentGeneration(): void {
    // Get the Guzzle HTTP client and make a direct request to the mock endpoint.
    $httpClient = $this->container->get('http_client');
    $config = $this->container->get('config.factory')->get('conductor.settings');
    // api.conductor.com is hooked in http_request_mock.
    $baseUrl = $config->get('api_url') ?? 'https://api.conductor.com';

    // Make a direct HTTP request to get the PSR-7 response.
    // It's provided by the http_request_mock differently.
    // @see \Drupal\conductor_test\Plugin\ServiceMock\ApiConductorComPlugin::getResponse()
    $psr7Response = $httpClient->request(
      'POST',
      $baseUrl . '/v3/content-outline/content-generation?draft_id=test-draft-123'
    );

    // Verify response status and headers.
    $this->assertEquals(200, $psr7Response->getStatusCode());
    // This forces ConductorHttpApiClient to return a StreamedResponse.
    // @see ConductorHttpApiClient::request()
    $this->assertEquals('application/x-ndjson', $psr7Response->getHeaderLine('Content-Type'));

    // Read the body stream directly from the PSR-7 response.
    $body = $psr7Response->getBody();
    $output = (string) $body;

    // Parse NDJSON lines.
    $lines = array_filter(explode("\n", trim($output)));
    $this->assertGreaterThanOrEqual(2, count($lines), 'Should have at least 2 NDJSON lines');

    // Parse the first two lines.
    $firstLine = json_decode($lines[0], TRUE);
    $secondLine = json_decode($lines[1], TRUE);

    // Verify the first line is the start event.
    $this->assertIsArray($firstLine);
    $this->assertEquals('start', $firstLine['type']);
    $this->assertEquals('test-draft-123', $firstLine['draft_id']);

    // Verify the second line is the first chunk with "Introduction paragraph...".
    $this->assertIsArray($secondLine);
    $this->assertEquals('chunk', $secondLine['type']);
    $this->assertEquals('Introduction paragraph...', $secondLine['content']);
  }

}
