<?php

declare(strict_types=1);

namespace KupShop\OrderingBundle\Util\Purchase;

use KupShop\CatalogBundle\Entity\Product\ProductDiscountResult;
use KupShop\CatalogBundle\Entity\Wrapper\ProductPricesResultWrapper;
use KupShop\CatalogBundle\Util\Product\ProductDiscountCalculator;
use KupShop\ContentBundle\Entity\ProductUnified;
use KupShop\KupShopBundle\Context\CurrencyContext;
use KupShop\KupShopBundle\Util\Contexts;
use KupShop\KupShopBundle\Util\Price\Price;
use KupShop\KupShopBundle\Util\Price\PriceCalculator;
use KupShop\KupShopBundle\Wrapper\PriceWrapper;
use KupShop\OrderingBundle\Entity\Purchase\ProductPurchaseItem;

class PurchaseItemUtil
{
    protected ProductDiscountCalculator $productDiscountCalculator;

    public function __construct(ProductDiscountCalculator $productDiscountCalculator)
    {
        $this->productDiscountCalculator = $productDiscountCalculator;
    }

    public function getProductItemDiscount(ProductPurchaseItem $purchaseItem): \Decimal
    {
        $itemPriceWithDiscounts = $purchaseItem->getPriceWithDiscounts();
        $itemPriceWithoutDiscounts = $purchaseItem->getPrice();

        $purchaseItemDiscount = $this->calculatePercentageDiscount($itemPriceWithDiscounts, $itemPriceWithoutDiscounts);

        $result = $this->getProductItemDiscountResult($purchaseItem);

        if ($purchaseItemDiscount->isPositive() && $result->discount->isPositive()) {
            // secist slevu z kosiku a slevu z produktu
            $actualDiscount = \DecimalConstants::hundred()->sub($purchaseItemDiscount)->div(\DecimalConstants::hundred());
            $addDiscount = \DecimalConstants::hundred()->sub($result->discount)->div(\DecimalConstants::hundred());
            $purchaseItemDiscount = \DecimalConstants::one()->sub($actualDiscount->mul($addDiscount))->mul(\DecimalConstants::hundred());
        } elseif ($result->discount->isPositive()) {
            $purchaseItemDiscount = $result->discount;
        }

        return $purchaseItemDiscount;
    }

    public function getProductItemDiscountResult(ProductPurchaseItem $purchaseItem): ProductDiscountResult|ProductPricesResultWrapper
    {
        return $this->productDiscountCalculator->calculate(
            new ProductUnified($purchaseItem->getProduct())
        );
    }

    private function calculatePercentageDiscount(Price $priceWithDiscount, Price $priceWithoutDiscount): \Decimal
    {
        if ($priceWithoutDiscount->getPriceWithVat()->isZero()) {
            return \DecimalConstants::zero();
        }

        return $priceWithoutDiscount->getPriceWithVat()->sub($priceWithDiscount->getPriceWithVat())->div($priceWithoutDiscount->getPriceWithVat())->mul(\DecimalConstants::hundred());
    }

    public function getProductItemOriginalPrice(ProductPurchaseItem $purchaseItem): Price
    {
        $priceOriginal = $this->getProductItemDiscountResult($purchaseItem)->priceOriginal;

        if ($priceOriginal) {
            $currency = Contexts::get(CurrencyContext::class)->getActive();
            $priceOriginal = PriceCalculator::convert(PriceWrapper::unwrap($priceOriginal), $currency);

            return new Price(
                $priceOriginal->getPriceWithoutVat()->mul(toDecimal($purchaseItem->getPieces())),
                $priceOriginal->getCurrency(),
                $priceOriginal->getVat()
            );
        }

        return $purchaseItem->getPrice();
    }
}
