<?php

declare(strict_types=1);

/*
 * This file is part of the VITICORE2 package.
 *
 * (c) CP Creation <web@cpcreation.fr>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace CpCreation\VitiCore\Tests\Commerce\Catalog\Outbox;

use CpCreation\VitiCore\Commerce\Catalog\Configuration\CatalogHubConfiguration;
use CpCreation\VitiCore\Commerce\Catalog\Configuration\CatalogIntegrationConfiguration;
use CpCreation\VitiCore\Commerce\Catalog\Configuration\CatalogWebhookEndpointResolver;
use CpCreation\VitiCore\Commerce\Catalog\Model\CatalogChange;
use CpCreation\VitiCore\Commerce\Catalog\Model\CatalogChangeType;
use CpCreation\VitiCore\Commerce\Catalog\Model\CatalogResourceType;
use CpCreation\VitiCore\Commerce\Catalog\Outbox\CatalogWebhookRequestFactory;
use CpCreation\VitiCore\Commerce\Catalog\Outbox\CatalogWebhookSigner;
use PHPUnit\Framework\TestCase;
use Ramsey\Uuid\Uuid;

final class CatalogWebhookRequestFactoryTest extends TestCase
{
    private const string INSTANCE_ID = '7ad9e145-910f-4de4-9cec-5f832494adef';
    private const string EVENT_ID = '018f6f62-5279-7ae0-a17f-b0fdd21b6880';
    private const string SECRET = '0123456789abcdef0123456789abcdef';

    public function testRequestUsesExactBodyBytesForItsHmacSignature(): void
    {
        $change = new CatalogChange(
            instanceId: self::INSTANCE_ID,
            type: CatalogChangeType::PRODUCT_CHANGED,
            resourceType: CatalogResourceType::PRODUCT,
            resourceId: 'catalog-product-id',
            occurredAt: new \DateTimeImmutable('2026-07-22T09:58:00+00:00'),
            eventId: Uuid::fromString(self::EVENT_ID),
        );
        $property = new \ReflectionProperty($change, 'cursor');
        $property->setValue($change, 42);

        $configuration = new CatalogIntegrationConfiguration(
            enabled: true,
            instanceId: self::INSTANCE_ID,
            apiTokenHash: hash('sha256', 'central-token'),
            currency: 'EUR',
        );
        $webhookEndpointResolver = new CatalogWebhookEndpointResolver(
            $configuration,
            new CatalogHubConfiguration('', '', '', '', '', '', false),
            'https://hub.example/webhooks/catalog',
            self::SECRET,
        );
        $signer = new CatalogWebhookSigner();
        $request = new CatalogWebhookRequestFactory($webhookEndpointResolver, $signer)->create(
            $change,
            new \DateTimeImmutable('2026-07-22T10:00:00+00:00'),
        );

        self::assertSame(self::EVENT_ID, $request->headers['Idempotency-Key']);
        self::assertSame(self::INSTANCE_ID, $request->headers['X-Serenity-Instance']);
        self::assertSame(
            $signer->sign(self::SECRET, $request->headers['X-Serenity-Timestamp'], $request->body),
            $request->headers['X-Serenity-Signature'],
        );
        self::assertSame([
            'schema_version' => '1.0',
            'cursor' => 42,
            'event_id' => self::EVENT_ID,
            'instance_id' => self::INSTANCE_ID,
            'type' => 'product.changed',
            'resource_type' => 'product',
            'resource_id' => 'catalog-product-id',
            'occurred_at' => '2026-07-22T09:58:00+00:00',
        ], json_decode($request->body, true, flags: \JSON_THROW_ON_ERROR));
    }
}
