<?php

/*
 * 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\Altcha;

use CpCreation\AltchaBundle\Model\ScopeDefinition;
use CpCreation\VitiCore\Bridge\Symfony\Bundle\Altcha\VitiCoreAltchaProtection;
use CpCreation\VitiCore\Bridge\Symfony\Bundle\Altcha\VitiCoreAltchaScopeProvider;
use CpCreation\VitiCore\Bridge\Symfony\Bundle\Form\Site\ContactFormType;
use CpCreation\VitiCore\Bridge\Symfony\Bundle\Form\Site\Order\CheckoutType;
use CpCreation\VitiCore\Bridge\Symfony\Bundle\Form\Site\PaymentType;
use CpCreation\VitiCore\Bridge\Symfony\Bundle\Form\Site\ProductReviewReportType;
use CpCreation\VitiCore\Bridge\Symfony\Bundle\Form\Site\ProductReviewSubmissionType;
use CpCreation\VitiCore\Bridge\Symfony\Bundle\Form\Site\Security\RegisterConfirmType;
use CpCreation\VitiCore\Bridge\Symfony\Bundle\Form\Site\Security\ResetPasswordType;
use CpCreation\VitiCore\Bridge\Symfony\Bundle\Form\Site\Withdrawal\WithdrawalRequestType;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;

final class VitiCoreAltchaProtectionTest extends TestCase
{
    #[DataProvider('protectedForms')]
    public function testItMapsOnlyExplicitlyProtectedVitiCoreForms(
        string $formType,
        string $scope,
        array $partialLiveActions = [],
        array $finalLiveActions = [],
    ): void {
        self::assertSame($scope, VitiCoreAltchaProtection::scopeFor($formType));
        self::assertSame($partialLiveActions, VitiCoreAltchaProtection::partialLiveActionsFor($formType));
        self::assertSame($finalLiveActions, VitiCoreAltchaProtection::finalLiveActionsFor($formType));
        self::assertSame([], array_values(array_intersect($partialLiveActions, $finalLiveActions)));
    }

    public function testBusinessGatedReviewAndCheckoutRemainOutsideTheProtectionContract(): void
    {
        self::assertNull(VitiCoreAltchaProtection::scopeFor(ProductReviewSubmissionType::class));
        self::assertNull(VitiCoreAltchaProtection::scopeFor(CheckoutType::class));
        self::assertSame([], VitiCoreAltchaProtection::partialLiveActionsFor(ProductReviewSubmissionType::class));
        self::assertSame([], VitiCoreAltchaProtection::partialLiveActionsFor(CheckoutType::class));
        self::assertSame([], VitiCoreAltchaProtection::finalLiveActionsFor(ProductReviewSubmissionType::class));
        self::assertSame([], VitiCoreAltchaProtection::finalLiveActionsFor(CheckoutType::class));
    }

    public function testScopeProviderDeclaresExactlyTheSixProtectedScopes(): void
    {
        $definitions = iterator_to_array((new VitiCoreAltchaScopeProvider())->scopes());

        self::assertContainsOnlyInstancesOf(ScopeDefinition::class, $definitions);
        self::assertSame(VitiCoreAltchaProtection::scopes(), array_map(
            static fn (ScopeDefinition $definition): string => $definition->name,
            $definitions,
        ));
        self::assertSame([
            'site.contact',
            'security.registration_confirm',
            'security.password_reset',
            'payment.online',
            'marketing.product_review_report',
            'shop.withdrawal',
        ], VitiCoreAltchaProtection::scopes());
        self::assertSame([
            'Contact',
            'Confirmation d’inscription',
            'Réinitialisation du mot de passe',
            'Paiement en ligne',
            'Signalement d’un avis',
            'Rétractation',
        ], array_map(
            static fn (ScopeDefinition $definition): string => $definition->label,
            $definitions,
        ));
        self::assertContains('payment.online', VitiCoreAltchaProtection::scopes());
        self::assertNotContains('marketing.product_review_submission', VitiCoreAltchaProtection::scopes());
    }

    public static function protectedForms(): iterable
    {
        yield 'contact' => [
            ContactFormType::class,
            'site.contact',
            [],
            ['submitContact'],
        ];
        yield 'confirmation inscription' => [
            RegisterConfirmType::class,
            'security.registration_confirm',
            ['validatePasswords'],
            ['submitRegisterConfirm'],
        ];
        yield 'réinitialisation mot de passe' => [
            ResetPasswordType::class,
            'security.password_reset',
            ['validatePasswords'],
            ['submitResetPassword'],
        ];
        yield 'paiement en ligne' => [
            PaymentType::class,
            'payment.online',
            [],
            ['submitPayment'],
        ];
        yield 'signalement avis produit' => [
            ProductReviewReportType::class,
            'marketing.product_review_report',
        ];
        yield 'rétractation' => [WithdrawalRequestType::class, 'shop.withdrawal'];
    }
}
