<?php

declare(strict_types=1);

namespace CpCreation\VitiCore\Tests\Command;

use CpCreation\VitiCore\Bridge\Symfony\Bundle\Command\TestAbandonedCartReminderCommand;
use CpCreation\VitiCore\Cart\Model\Cart;
use CpCreation\VitiCore\Cart\Repository\CartRepository;
use CpCreation\VitiCore\Marketing\AbandonedCartRuleMatcher;
use CpCreation\VitiCore\Marketing\AbandonedCartRuleSelector;
use CpCreation\VitiCore\Marketing\Model\AbandonedCartConfiguration;
use CpCreation\VitiCore\Marketing\Model\AbandonedCartRule;
use CpCreation\VitiCore\Product\Model\ProductPriceGroup;
use CpCreation\VitiCore\Product\Repository\ProductPriceCodeRepository;
use CpCreation\VitiCore\Product\Repository\ProductPriceGroupRepository;
use PHPUnit\Framework\TestCase;

final class TestAbandonedCartReminderCommandTest extends TestCase
{
    public function testForceDoesNotSelectRuleWhenCartDoesNotMeetBusinessConditions(): void
    {
        [$command, $configuration, $rule, $cart] = $this->createScenario();
        $rule->setMinSubtotalTTC(50000);

        $selectedRule = $this->selectRule($command, $configuration, $rule, $cart, force: true);

        self::assertNull($selectedRule);
    }

    public function testForceSelectsEligibleRuleWithoutWaitingForAbandonmentDelay(): void
    {
        [$command, $configuration, $rule, $cart] = $this->createScenario();
        $rule->setMinSubtotalTTC(0);
        $rule->setDelayHours(48);

        $selectedRule = $this->selectRule($command, $configuration, $rule, $cart, force: true);

        self::assertSame($rule, $selectedRule);
    }

    public function testForceDoesNotSelectDisabledRule(): void
    {
        [$command, $configuration, $rule, $cart] = $this->createScenario();
        $rule->setEnabled(false);

        $selectedRule = $this->selectRule($command, $configuration, $rule, $cart, force: true);

        self::assertNull($selectedRule);
    }

    public function testForceDoesNotSelectRuleFromDisabledCampaign(): void
    {
        [$command, $configuration, $rule, $cart] = $this->createScenario();
        $configuration->setEnabled(false);

        $selectedRule = $this->selectRule($command, $configuration, $rule, $cart, force: true);

        self::assertNull($selectedRule);
    }

    /**
     * @return array{TestAbandonedCartReminderCommand, AbandonedCartConfiguration, AbandonedCartRule, Cart}
     */
    private function createScenario(): array
    {
        $configuration = new AbandonedCartConfiguration();
        $configuration->setEnabled(true);

        $priceGroup = new ProductPriceGroup();
        $rule = new AbandonedCartRule($configuration);
        $rule->setPriceGroup($priceGroup);

        $priceGroupRepository = $this->createStub(ProductPriceGroupRepository::class);
        $priceGroupRepository->method('getGroupByDefault')->willReturn($priceGroup);
        $matcher = new AbandonedCartRuleMatcher(
            $this->createStub(CartRepository::class),
            $this->createStub(ProductPriceCodeRepository::class),
            $priceGroupRepository,
        );
        $selector = new AbandonedCartRuleSelector($matcher);

        $reflection = new \ReflectionClass(TestAbandonedCartReminderCommand::class);
        /** @var TestAbandonedCartReminderCommand $command */
        $command = $reflection->newInstanceWithoutConstructor();
        $reflection->getProperty('ruleMatcher')->setValue($command, $matcher);
        $reflection->getProperty('ruleSelector')->setValue($command, $selector);

        return [$command, $configuration, $rule, new Cart()];
    }

    private function selectRule(
        TestAbandonedCartReminderCommand $command,
        AbandonedCartConfiguration $configuration,
        AbandonedCartRule $rule,
        Cart $cart,
        bool $force,
    ): ?AbandonedCartRule {
        $method = new \ReflectionMethod($command, 'selectRule');

        return $method->invoke(
            $command,
            [$rule],
            $rule->getId()->toString(),
            $cart,
            $configuration,
            new \DateTimeImmutable(),
            $force,
        );
    }
}
