<?php

namespace KupShop\ProductsChargesBundle\Actions;

use KupShop\KupShopBundle\Context\CurrencyContext;
use KupShop\KupShopBundle\Context\VatContext;
use KupShop\KupShopBundle\Util\Contexts;
use KupShop\KupShopBundle\Util\Price\Price;
use KupShop\KupShopBundle\Util\Price\PriceCalculator;
use KupShop\KupShopBundle\Util\Price\TotalPrice;
use KupShop\OrderDiscountBundle\Actions\AbstractAction;
use KupShop\OrderDiscountBundle\Actions\Frontend\HandlerInterface;
use KupShop\OrderDiscountBundle\Entity\OrderDiscount;
use KupShop\OrderingBundle\Entity\Purchase\ChargePurchaseItem;
use KupShop\OrderingBundle\Entity\Purchase\ProductPurchaseItem;
use KupShop\OrderingBundle\Entity\Purchase\PurchaseState;
use KupShop\OrderingBundle\Util\Order\OrderItemInfo;
use KupShop\ProductsChargesBundle\Actions\Frontend\OrdersChargesHandler;
use Query\Operator;

class OrdersChargesAction extends AbstractAction
{
    protected static $type = 'orders_charge';
    protected static $position = 130;
    protected $adminTemplate = 'actions/orders_charges.tpl';
    protected $translationSection = 'productsCharges';

    private $ordersChargesHandler;

    public function __construct(OrdersChargesHandler $ordersChargesHandler)
    {
        $this->ordersChargesHandler = $ordersChargesHandler;
    }

    public static function calculatePercentCharges(TotalPrice $totalPrice, $percentage)
    {
        return $totalPrice
            ->getPriceWithoutVat()
            ->div(toDecimal('100.0'))
            ->mul(toDecimal($percentage));
    }

    public function applyResult(PurchaseState &$purchaseState, OrderDiscount $orderDiscount, array $data)
    {
        $charge = sqlQueryBuilder()->select('*')->from('charges')
            ->where(Operator::equals(['id' => $data['id_charge']]))
            ->execute()->fetch();
        if ($charge) {
            $required = $charge['required'] ?? null;
            $defaultChecked = $charge['checked'] ?? null;
            $checked = ($data['handled']['checked'] ?? $required == 'Y' ?: $defaultChecked);
            if ($checked == 'Y') {
                $name = $orderDiscount->getDisplayName();
                $note = ['item_type' => OrderItemInfo::TYPE_CHARGE, 'id_charge' => $data['id_charge']];

                $product = false;
                if ($id_product = $charge['id_product'] ?? null) {
                    if ($id_variation = $charge['id_variation'] ?? null) {
                        $product = new \Variation($id_product, $id_variation);
                    } else {
                        $product = new \Product($id_product);
                    }
                    if (!$product->createFromDB()) {
                        $product = false;
                    }
                }

                if ($product) {
                    // uplatnit sazbu DPH podle priplatkoveho produktu
                    $vat = getVat($product->vat_id);
                } elseif (is_null($charge['vat'])) {
                    // uplatnit sazbu DPH podle produktů v objednávce
                    $vat = $purchaseState->getDeliveryVat();
                } else {
                    $vat = getVat($charge['vat']);
                    if ($vat != 0) {
                        // v případě OSS se použije výchozí DPH dané země
                        $vat = Contexts::get(VatContext::class)->isCountryOssActive() ? getVat() : $vat;
                    }
                }

                $discountPrice = toDecimal($charge['price']);
                $currency = Contexts::get(CurrencyContext::class)->getOrDefault($charge['currency'] ?? null);
                if ($charge['percentage'] ?? false) {
                    $discountPrice = self::calculatePercentCharges($purchaseState->getTotalPrice(), $charge['percentage']);
                    $currency = $purchaseState->getTotalPrice()->getCurrency();
                }
                $discountPrice = new Price($discountPrice, $currency, $vat);
                $discountPrice = PriceCalculator::convert($discountPrice, $purchaseState->getTotalPrice()->getCurrency());
                $discountPriceValue = $discountPrice->getPriceWithoutVat(); // kvuli spravnemu zaokrouhleni
                $discountPrice = new Price($discountPriceValue, $discountPrice->getCurrency(), $vat);
                if ($product) {
                    $purchaseItem = new ProductPurchaseItem($id_product, $id_variation ?? null, 1,
                        $discountPrice, $note, $orderDiscount->getId());
                    $purchaseItem->id_charge = $data['id_charge'];
                    $purchaseItem->setName($name);
                } else {
                    $purchaseItem = new ChargePurchaseItem($name, $discountPrice, $data['id_charge'], $orderDiscount->getId(), $note);
                }
                $purchaseState->addCharge($purchaseItem);
                $purchaseState->addUsedDiscount($orderDiscount->getId());
                if ($message = $data['messages']['success'] ?? '') {
                    $this->messages['success'] = $message;
                }
            } else {
                if ($message = $data['messages']['warning'] ?? '') {
                    $this->messages['warning'] = $message;
                }
            }
        }
    }

    public function getFrontendHandler(): ?HandlerInterface
    {
        return $this->ordersChargesHandler;
    }

    protected function getVars($vars)
    {
        $vars['charges'] = sqlFetchAll(
            sqlQueryBuilder()
                ->select('id, IF(admin_title != "", admin_title, title) as title')->from('charges')
                ->andWhere("type = 'order'")
                ->execute(),
            ['id' => 'title']
        );

        return $vars;
    }
}
