<?php

declare(strict_types=1);

namespace CpCreation\VitiCore\Tests\Cart;

use CpCreation\VitiCore\Cart\CartPromo;
use CpCreation\VitiCore\Cart\Model\Cart;
use CpCreation\VitiCore\Cart\Model\CartItem;
use CpCreation\VitiCore\Cart\Model\Promo;
use CpCreation\VitiCore\Cart\PromoEligibilityResolver;
use CpCreation\VitiCore\Cart\Repository\CartRepository;
use CpCreation\VitiCore\Cart\Repository\PromoRepository;
use CpCreation\VitiCore\Product\DegressiveCalculatorInterface;
use CpCreation\VitiCore\Product\DegressiveContextFactory;
use CpCreation\VitiCore\Product\DegressiveManager;
use CpCreation\VitiCore\Product\Model\ProductType;
use CpCreation\VitiCore\Product\Model\ProductVariant;
use CpCreation\VitiCore\Shop\Repository\ShippingCountryRepository;
use CpCreation\VitiCore\Shop\Repository\ShippingCountyRepository;
use CpCreation\VitiCore\Shop\Repository\ShippingZoneRepository;
use PHPUnit\Framework\TestCase;

final class PromoEligibilityResolverTest extends TestCase
{
    public function testPromoIsRejectedWhenCartSubtotalExceedsMaximum(): void
    {
        $cart = $this->createCartWithSubtotalTTC(10001);
        $promo = $this->createActivePromo();
        $promo->setMaxSubtotalTTC(10000);

        $result = $this->createResolver()->resolvePromo($promo, $cart);

        self::assertSame(CartPromo::STATUS_INVALID, $result->status);
        self::assertSame('cart.promo.invalid_amount', $result->messageKey);
    }

    public function testPromoIsAppliedWhenCartSubtotalEqualsMaximum(): void
    {
        $cart = $this->createCartWithSubtotalTTC(10000);
        $promo = $this->createActivePromo();
        $promo->setMaxSubtotalTTC(10000);

        $result = $this->createResolver()->resolvePromo($promo, $cart);

        self::assertSame(CartPromo::STATUS_APPLIED, $result->status);
        self::assertNull($result->messageKey);
    }

    private function createActivePromo(): Promo
    {
        $promo = new Promo();
        $promo->setTitle('RELANCE');
        $promo->setBeginAt(new \DateTimeImmutable('-1 day'));
        $promo->setEndAt(new \DateTimeImmutable('+1 day'));

        return $promo;
    }

    private function createCartWithSubtotalTTC(int $subtotalTTC): Cart
    {
        $type = $this->createStub(ProductType::class);
        $type->method('getEquivalency')->willReturn(1.0);
        $variant = $this->createStub(ProductVariant::class);
        $variant->method('getType')->willReturn($type);
        $item = $this->createMock(CartItem::class);
        $item->method('getTotalFinalTTC')->willReturn($subtotalTTC);
        $item->method('getVariant')->willReturn($variant);
        $item->method('getQuantity')->willReturn(1);
        $cart = new Cart();
        $cart->addItem($item);

        return $cart;
    }

    private function createResolver(): PromoEligibilityResolver
    {
        /** @var DegressiveContextFactory $contextFactory */
        $contextFactory = new \ReflectionClass(DegressiveContextFactory::class)->newInstanceWithoutConstructor();
        $degressiveManager = new DegressiveManager(
            $contextFactory,
            $this->createStub(DegressiveCalculatorInterface::class),
        );

        return new PromoEligibilityResolver(
            $this->createStub(PromoRepository::class),
            $this->createStub(CartRepository::class),
            $degressiveManager,
            $this->createStub(ShippingCountryRepository::class),
            $this->createStub(ShippingCountyRepository::class),
            $this->createStub(ShippingZoneRepository::class),
        );
    }
}
