<?php

declare(strict_types=1);

namespace Drupal\Tests\native_observability_cache_observer\Unit\Service;

use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Cache\CacheableResponse;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Config\ImmutableConfig;
use Drupal\Tests\UnitTestCase;
use Drupal\native_observability_cache_observer\Service\CacheSpanEnrichmentProvider;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

/**
 * Covers request summary cache enrichment generation.
 */
final class CacheSpanEnrichmentProviderTest extends UnitTestCase {

  /**
   * Verifies that the provider returns an empty payload when capture is off.
   */
  public function testBuildRequestSummaryPayloadReturnsEmptyArrayWhenCaptureIsDisabled(): void {
    $provider = new CacheSpanEnrichmentProvider($this->buildConfigFactory([
      'capture_enabled' => FALSE,
      'capture_response_headers' => TRUE,
      'capture_response_cacheability' => TRUE,
    ]));

    $payload = $provider->buildRequestSummaryPayload(new Request(), new Response());

    $this->assertSame([], $payload);
  }

  /**
   * Verifies that response headers and cacheability metadata are normalized.
   */
  public function testBuildRequestSummaryPayloadCollectsConfiguredCacheSignals(): void {
    $provider = new CacheSpanEnrichmentProvider($this->buildConfigFactory([
      'capture_enabled' => TRUE,
      'capture_response_headers' => TRUE,
      'capture_response_cacheability' => TRUE,
    ]));

    $response = new CacheableResponse('', 200, [
      'X-Drupal-Cache' => 'hit',
      'X-Drupal-Dynamic-Cache' => 'uncacheable',
    ]);

    $response->addCacheableDependency(
      (new CacheableMetadata())
        ->setCacheTags(['node:1', 'config:system.site'])
        ->setCacheContexts(['user.permissions'])
        ->setCacheMaxAge(3600)
    );

    $payload = $provider->buildRequestSummaryPayload(new Request(), $response);

    $this->assertSame('HIT', $payload['cache']['page_cache_status']);
    $this->assertSame('UNCACHEABLE', $payload['cache']['dynamic_page_cache_status']);
    $this->assertSame('CACHEABLE', $payload['cache']['cacheability_status']);
    $this->assertSame(2, $payload['cache']['tags_count']);
    $this->assertSame(1, $payload['cache']['contexts_count']);
    $this->assertSame(3600, $payload['cache']['max_age']);
  }

  /**
   * Builds a config factory mock for the tested provider.
   *
   * @param array<string, mixed> $values
   *   The configuration map returned by ImmutableConfig::get().
   */
  private function buildConfigFactory(array $values): ConfigFactoryInterface {
    $config = $this->createMock(ImmutableConfig::class);
    $config->method('get')->willReturnCallback(static fn(string $key) => $values[$key] ?? NULL);

    $factory = $this->createMock(ConfigFactoryInterface::class);
    $factory->method('get')->with('native_observability_cache_observer.settings')->willReturn($config);

    return $factory;
  }

}
