<?php

declare(strict_types=1);

namespace CpCreation\AltchaBundle\Tests\PublicApi;

use CpCreation\AltchaBundle\Contract\ScopeProviderInterface;
use CpCreation\AltchaBundle\Model\ScopeDefinition;
use CpCreation\AltchaBundle\Scope\ScopeRegistry;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;

final class ScopeRegistryTest extends TestCase
{
    public function testCustomScopesAreAcceptedAndExposedAsAManifest(): void
    {
        $registry = new ScopeRegistry([
            'site.contact' => 'Contact',
            'custom.project_form' => 'Project form',
        ]);

        self::assertTrue($registry->contains('custom.project_form'));
        self::assertSame(
            ['custom.project_form', 'site.contact'],
            array_map(static fn ($scope): string => $scope->name, $registry->manifest()->scopes),
        );
    }

    public function testTaggedStyleProvidersCanContributeScopesWithoutAnEnum(): void
    {
        $provider = new class implements ScopeProviderInterface {
            public function scopes(): iterable
            {
                yield new ScopeDefinition('viticore.review', 'Product review');
            }
        };
        $registry = new ScopeRegistry(['custom.form' => 'Custom'], [$provider]);

        self::assertTrue($registry->contains('viticore.review'));
        self::assertSame(
            ['custom.form', 'viticore.review'],
            array_map(static fn (ScopeDefinition $scope): string => $scope->name, $registry->manifest()->scopes),
        );
    }

    #[DataProvider('invalidScopes')]
    public function testInvalidScopeIdentifiersAreRejected(string $scope): void
    {
        $this->expectException(\InvalidArgumentException::class);

        new ScopeRegistry([$scope => 'Invalid']);
    }

    public static function invalidScopes(): iterable
    {
        yield [''];
        yield ['Checkout Form'];
        yield ['UPPER.case'];
        yield ['../escape'];
        yield [str_repeat('a', 65)];
    }
}
