<?php

namespace KupShop\FeedsBundle\Wrapper;

use KupShop\FeedGeneratorBundle\Expressions\ExpressionObjectTrait;
use KupShop\FeedGeneratorBundle\Expressions\IExpressionObject;
use KupShop\FeedGeneratorBundle\Utils\IObjectInfo;
use KupShop\KupShopBundle\Context\CurrencyContext;
use KupShop\KupShopBundle\Context\PriceLevelContext;
use KupShop\KupShopBundle\Util\Contexts;
use KupShop\KupShopBundle\Util\Price\Price;
use KupShop\KupShopBundle\Util\Price\PriceCalculator;
use KupShop\KupShopBundle\Util\Price\ProductPrice;

class PriceLevelWrapper extends BaseWrapper implements IExpressionObject, IObjectInfo, \ArrayAccess
{
    use ExpressionObjectTrait;

    protected \Product $product;

    /** @var int id priceLevel */
    protected $object;

    protected function getPriceLevel(): \PriceLevel
    {
        return Contexts::get(PriceLevelContext::class)->getById($this->object);
    }

    protected function getDiscount(): array
    {
        $priceLevel = $this->getPriceLevel();

        $idSections = null;
        if ($priceLevel->sections) {
            $idSections = array_values(array_map(fn ($s) => $s->getId(), $this->product->sections));
        }

        return $priceLevel->getDiscount($this->product->id, $idSections, $this->product->idProducer, $this->product);
    }

    /** Název cenové hladiny */
    public function field_name(): string
    {
        return $this->getPriceLevel()->name;
    }

    /** Cena */
    public function field_price(): PriceWrapper
    {
        $discount = $this->getDiscount();

        $price = $this->product->getProductPrice();

        $currencyContext = Contexts::get(CurrencyContext::class);

        switch ($discount['unit']) {
            case 'perc':
                $price = (clone $price)->addDiscount(toDecimal($discount['discount']));
                break;
            case 'price':
                $discountPrice = new Price(toDecimal($discount['discount']), $currencyContext->getDefault(), $this->product->vat);
                $discountPrice = PriceCalculator::convert($discountPrice, $price->getCurrency());
                $price = PriceCalculator::sub(PriceCalculator::toPrice($price), $discountPrice);
                $price = new ProductPrice($price->getPriceWithoutVat(false), $price->getCurrency(), $price->getVat());
                break;
        }

        $priceWrapper = new PriceWrapper();
        $priceWrapper->setObject($price);

        return $priceWrapper;
    }

    /** Sleva v procentech */
    public function field_discount_percent(): ?float
    {
        $discount = $this->getDiscount();
        if ($discount['unit'] == 'perc') {
            return $discount['discount'];
        }

        return null;
    }

    /** Sleva v korunách */
    public function field_discount_price(): ?float
    {
        $discount = $this->getDiscount();
        if ($discount['unit'] == 'price') {
            return $discount['discount'];
        }

        return null;
    }

    /** @private */
    public function setProduct(\Product $product): PriceLevelWrapper
    {
        $this->product = $product;

        return $this;
    }
}
