<?php

declare(strict_types=1);

namespace KupShop\PreordersBundle\Tests\Utils;

use KupShop\DevelopmentBundle\Util\Tests\CartTestTrait;
use KupShop\OrderingBundle\Util\Purchase\PurchaseUtil;
use KupShop\PreordersBundle\Service\DynamicPrices;
use KupShop\PreordersBundle\Service\PreorderUtil;
use KupShop\PreordersBundle\Tests\PreordersTestHelper;
use Query\Operator;
use Query\QueryBuilder;

class PreordersUtilsTest extends \DatabaseTestCase
{
    use PreordersTestHelper;
    use CartTestTrait;

    public function data_productLists(): array
    {
        return [
            [$this->createProductList(true)],
            [$this->createProductList(false)],
        ];
    }

    /**
     * @dataProvider data_productLists
     */
    public function testCreatePurchaseState(\ProductList $productList): void
    {
        $products = $productList->getProducts();
        $purchaseState = PreorderUtil::toPurchaseState(
            $products,
            customPriceField: 'test_piece_price',
        );

        $this->assertCount(3, $purchaseState->getProducts());

        foreach ($purchaseState->getProducts() as $purchaseItem) {
            $key = $purchaseItem->id_product.($purchaseItem->id_variation ? '/'.$purchaseItem->id_variation : '');

            $this->assertEquals(
                self::$itemsWithValues[$key]['pieces'],
                $purchaseItem->getPieces(),
            );

            $this->assertEqualsWithDelta(
                (float) self::$itemsWithValues[$key]['piece_price'],
                $purchaseItem->getPiecePriceWithoutVat()->asFloat(),
                delta: 0.25, // to už je docela dost, ne?
            );
        }

        $this->get(PurchaseUtil::class)->recalculateTotalPrices($purchaseState);

        $this->assertEqualsWithDelta(
            16296,
            $purchaseState->getTotalPrice()->getPriceWithoutVat()->asFloat(),
            delta: 0.25,
        );
    }

    public function testCalcBasePrice()
    {
        $userPreorder = $this->createTestUserPreorder();
        $list = $this->get(PreorderUtil::class)->getPreorderProductList($userPreorder->getItems(), false);
        $products = $list->getProducts();
        $refList = (new \ProductList(true))
            ->andSpec(function (QueryBuilder $qb) use ($products) {
                $qb->andWhere(Operator::inIntArray($products->getProductIds(), 'p.id'));
            });

        $this->get(DynamicPrices::class)->inject($products, $refList, $userPreorder->getPreorder());
        $basePrice = $this->get(PreorderUtil::class)->calculateBasePrice($products);

        $this->assertEqualsWithDelta(
            17642,
            $basePrice->getPriceWithoutVat()->asFloat(),
            delta: 1,
        );
    }

    /**
     * Termín předobjednávek by se měl uzavřít (přestat zobrazovat) když je preorders_dates.date_end v minulosti.
     * Tzn. že pokud date_end je dnes, tak je termín ještě otevřený.
     */
    public function testOpenDates(): void
    {
        $dates = $this->createTestMultipleDates();

        $expectedOpenDates = array_column(array_filter(
            $dates,
            fn (array $date) => $date['date_end'] >= (new \DateTimeImmutable())->format('Y-m-d'),
        ), 'id');

        /** Uživatel s ID=3 má přístupné všechny předobjednávky */
        $user = \User::createFromId(3);

        $actualOpenDates = array_column(PreorderUtil::getOpenDates($user), 'id');

        $this->assertEquals($expectedOpenDates, $actualOpenDates, 'Nefunguje PreorderUtil::getOpenDates :)');
    }
}
