<?php

declare(strict_types=1);

namespace CpCreation\VitiCore\Tests\SocialPublishing;

use CpCreation\VitiCore\Commerce\Catalog\Configuration\CatalogConfigurationProvider;
use CpCreation\VitiCore\Commerce\Catalog\Configuration\CatalogConfigurationSnapshot;
use CpCreation\VitiCore\SocialPublishing\HttpSocialPublishingHub;
use PHPUnit\Framework\TestCase;
use Symfony\Component\HttpClient\MockHttpClient;
use Symfony\Component\HttpClient\Response\MockResponse;

final class HttpSocialPublishingHubTest extends TestCase
{
    private const string INSTANCE_ID = '7ad9e145-910f-4de4-9cec-5f832494adef';

    public function testItExchangesTheEnrollmentCredentialAndReadsTypedChannels(): void
    {
        $calls = 0;
        $client = new MockHttpClient(function (string $method, string $url, array $options) use (&$calls): MockResponse {
            ++$calls;
            if (1 === $calls) {
                self::assertSame('POST', $method);
                self::assertSame(
                    'https://hub.example/api/integrations/serenity/' . self::INSTANCE_ID . '/tokens',
                    $url,
                );
                self::assertSame(
                    'Authorization: Bearer enrollment-token',
                    $options['normalized_headers']['authorization'][0],
                );
                self::assertSame(
                    ['scopes' => ['social:read']],
                    json_decode($options['body'], true, flags: \JSON_THROW_ON_ERROR),
                );

                return new MockResponse('{"access_token":"short-lived-token"}');
            }

            self::assertSame('GET', $method);
            self::assertSame(
                'https://hub.example/api/social/instances/' . self::INSTANCE_ID . '/channels',
                $url,
            );
            self::assertSame(
                'Authorization: Bearer short-lived-token',
                $options['normalized_headers']['authorization'][0],
            );

            return new MockResponse(json_encode([
                'data' => [[
                    'id' => '0198abcd-0000-7000-8000-000000000001',
                    'provider' => 'meta',
                    'external_id' => '123456789',
                    'name' => 'Champagne Exemple',
                    'type' => 'facebook_page',
                    'capabilities' => ['content_types' => ['text', 'image']],
                ]],
            ], \JSON_THROW_ON_ERROR));
        });
        $provider = $this->createStub(CatalogConfigurationProvider::class);
        $provider->method('current')->willReturn($this->configuration());

        $hub = new HttpSocialPublishingHub($provider, $client);
        $channels = $hub->channels();

        self::assertTrue($hub->isAvailable());
        self::assertCount(1, $channels);
        self::assertSame('meta', $channels[0]->provider);
        self::assertSame('facebook_page', $channels[0]->type);
        self::assertSame(['text', 'image'], $channels[0]->capabilities['content_types']);
        self::assertSame(2, $client->getRequestsCount());
    }

    private function configuration(): CatalogConfigurationSnapshot
    {
        return new CatalogConfigurationSnapshot(
            enabled: true,
            hubUrl: 'https://hub.example',
            instanceId: self::INSTANCE_ID,
            currency: 'EUR',
            authAudience: 'serenity:catalog',
            enrollmentToken: 'enrollment-token',
            webhookSecret: 'webhook-secret',
            webhookUrl: 'https://hub.example/webhooks',
            jwtIssuer: 'serenity-commerce-hub',
            jwtKeyId: 'hub-main',
            jwtPublicKeyPem: 'public-key',
        );
    }
}
