<?php

class ProductsPricelists extends Window
{
    public $priceListWorker;
    public $vat;
    protected $template = 'window/products.pricelists.tpl';

    private $productId;

    /** @var \Doctrine\ORM\EntityManager */
    private $em;

    public function __construct()
    {
        $this->em = \KupShop\KupShopBundle\Util\Compat\ServiceContainer::getService('doctrine.orm.entity_manager');
        $this->priceListWorker = \KupShop\KupShopBundle\Util\Compat\ServiceContainer::getService(\KupShop\PricelistBundle\Util\PriceListWorker::class);
    }

    public function get_vars()
    {
        $dbcfg = Settings::getDefault();
        $vars = parent::get_vars();

        $pageVars = getVal('body', $vars, []);

        $pageVars['ID'] = $this->getProductId();
        $pageVars['defaultPricelist'] = $this->getDefaultPricelist();
        $pageVars['defaultCurrency'] = $this->getDefaultCurrency();
        $pageVars['pricelists'] = $this->getPricelists();
        $pageVars['data'] = $this->getPricelistData();
        $pageVars['variations'] = $this->getVariations();
        $pageVars['vat'] = $this->getVat();
        $pageVars['data']['showPricesWithVat'] = $dbcfg['prod_prefer_price_vat'] == 'Y' || $dbcfg['prod_prefer_price_vat'] == 'F';

        $vars['body'] = $pageVars;

        return $vars;
    }

    public function handle()
    {
        parent::handle();

        $data = parent::getData();
        unset($data['ID'], $data['showPricesWithVat']);
        if (!empty($data)) {
            $this->handleUpdatePricelists();
        }
    }

    public function handleUpdatePricelists()
    {
        $data = parent::getData();
        $showVat = $data['showPricesWithVat'];
        unset($data['ID']);
        unset($data['showPricesWithVat']);
        foreach ($data as $pricelistId => $options) {
            $options['showVat'] = $showVat;
            if ($pricelistId > 0) {
                $this->priceListWorker->updatePricelists($pricelistId, $options, $this->getProductId(), $this->getVat());
                // variations update
                if (isset($options['vars']) && $options['vars'] == 'true') {
                    foreach ($options['priceVar'] as $varId => $price) {
                        $discount = $options['discountVar'][$varId] ?? '';
                        $varOptions = [
                            'price' => $this->preparePrice($price),
                            'discount' => $this->preparePrice($discount),
                            'showVat' => $showVat,
                        ];
                        $this->priceListWorker->updatePricelists($pricelistId, $varOptions, $this->getProductId(), $this->getVat(), $varId);
                    }
                }
            // updating default pricelist
            } elseif ($pricelistId == 0) {
                $this->updateDefaultPricelist($options);
                // variations update in default pricelist
                if (isset($options['vars']) && $options['vars'] == 'true') {
                    foreach ($options['priceVar'] as $varId => $price) {
                        $this->updateDefaultVariations($varId, $this->preparePrice($price), $options['showVat']);
                    }
                }
            }
        }

        $this->returnOK();
    }

    public function handleUpdate()
    {
        if (getVal('submitUpdatePricelists')) {
            $data = parent::getData();
            $showVat = $data['showPricesWithVat'];
            unset($data['ID']);
            unset($data['showPricesWithVat']);
            foreach ($data as $pricelistId => $options) {
                $options['showVat'] = $showVat;
                if ($pricelistId > 0) {
                    $this->priceListWorker->updatePricelists($pricelistId, $options, $this->getProductId(), $this->getVat());
                    // variations update
                    if (isset($options['vars']) && $options['vars'] == 'true') {
                        foreach ($options['priceVar'] as $varId => $price) {
                            $this->priceListWorker->updatePricelists($pricelistId, ['price' => $this->preparePrice($price), 'showVat' => $showVat], $this->getProductId(), $this->getVat(), $varId);
                        }
                    }
                // updating default pricelist
                } elseif ($pricelistId == 0) {
                    $this->updateDefaultPricelist($options);
                    // variations update in default pricelist
                    if (isset($options['vars']) && $options['vars'] == 'true') {
                        foreach ($options['priceVar'] as $varId => $price) {
                            $this->updateDefaultVariations($varId, $this->preparePrice($price), $options['showVat']);
                        }
                    }
                }
            }
        }

        return true;
    }

    public function updateDefaultPricelist($data)
    {
        // vat remove before saving to database
        if ($data['showVat'] == 'Y') {
            $data['price'] = $this->priceListWorker->removeVatFromPrice($this->preparePrice($data['price']), $this->getVat());
        }

        $price = ['price' => $data['price'], 'discount' => $data['discount']];
        $where = ['id' => $this->getProductId()];
        $this->updateSQL('products', $price, $where);
    }

    public function updateDefaultVariations($varId, $price, $showVat)
    {
        $price = Decimal::create($price);
        // vat remove before saving to database
        if ($showVat == 'Y') {
            $price = $this->priceListWorker->removeVatFromPrice($price, $this->getVat());
        }

        if ($price->isZero()) {
            $price = null;
        }

        $this->updateSQL('products_variations', ['price' => $price], ['id' => $varId]);
    }

    /**
     * @param \KupShop\PricelistBundle\Entity\Pricelist $pricelist
     * @param Decimal                                   $price
     *
     * @return Decimal
     */
    public function recalcPriceFromCZK($pricelist, $price)
    {
        if ($pricelist) {
            if ($price) {
                return $price->div($pricelist->getCurrency()->getRate());
            }
        } else {
            if ($price) {
                $currency = $this->getDefaultCurrency();
                $rate = Decimal::create($currency['rate']);

                return $price->div($rate);
            }
        }

        return $price;
    }

    /**
     * @param \KupShop\I18nBundle\Entity\Currency $currency
     * @param string                              $price
     *
     * @return Decimal
     */
    public function recalcPriceToCZK($currency, $price)
    {
        $price = Decimal::create($price);

        return $price->mul($currency->getRate());
    }

    public function getDefaultCurrency()
    {
        $dbcfg = Settings::getDefault();

        return sqlQueryBuilder()
            ->select('id as code, symbol, rate')
            ->from('currencies')
            ->where('id = ?')->setParameter(0, $dbcfg->currency)
            ->setMaxResults(1)
            ->execute()->fetch();
    }

    public function getDefaultPricelist()
    {
        return sqlQueryBuilder()->select('price', 'discount')
                ->from('products')
                ->where('id = ?')->setParameter(0, $this->getProductId())
                ->execute()->fetch();
    }

    /* Variations data */
    public function getPricelistData()
    {
        $return = [];
        $repository = $this->em->getRepository(\KupShop\PricelistBundle\Entity\PricelistProduct::class);
        $data = $repository->findBy(['productId' => $this->getProductId()]);

        /** @var \KupShop\PricelistBundle\Entity\PricelistProduct $value */
        foreach ($data as $value) {
            // pricelists
            if ($value->getVariationId() == null) {
                $return[$value->getPricelist()->getId()]['pricelist'] = [
                    'pricelistId' => $value->getPricelist()->getId(),
                    'variationId' => $value->getVariationId(),
                    'price' => $value->getPrice(),
                    'discount' => $value->getDiscount(),
                ];
            } else { // variations
                if ($value->getPricelist()) {
                    $pricelistId = $value->getPricelist()->getId();
                } else {
                    $pricelistId = 0;
                }
                $return[$pricelistId][$value->getVariationId()] = [
                    'pricelistId' => $pricelistId,
                    'variationId' => $value->getVariationId(),
                    'price' => $value->getPrice(),
                    'discount' => $value->getDiscount(),
                ];
            }
        }

        return $return;
    }

    public function getVariations()
    {
        if (findModule('products_variations')) {
            $qb = sqlQueryBuilder()
                ->select('id, title, price')
                ->from('products_variations')
                ->where('id_product = ?')->setParameter(0, $this->getProductId())
                ->execute();

            if ($qb->rowCount() != 0) {
                $data = [];
                foreach ($qb as $var) {
                    $data[$var['id']]['id'] = $var['id'];
                    $data[$var['id']]['title'] = $var['title'];
                    $data[$var['id']]['price'] = $var['price'];
                }

                return $data;
            }
        }

        return false;
    }

    public function getVat()
    {
        if ($this->vat == null) {
            $this->vat = sqlQueryBuilder()
                ->select('v.vat')
                ->from('vats', 'v')
                ->leftJoin('v', 'products', 'p', 'v.id=p.vat')
                ->where('p.id = ?')->setParameter(0, $this->getProductId())
                ->execute()->fetchColumn();
        }

        return $this->vat;
    }

    public function getPricelists()
    {
        $repository = $this->em->getRepository(\KupShop\PricelistBundle\Entity\Pricelist::class);

        return $repository->findAll();
    }

    public function getProductId()
    {
        if ($this->productId == null) {
            $this->productId = getVal('ID');
        }

        return $this->productId;
    }

    protected function getObject()
    {
        return null;
    }
}

(new ProductsPricelists())->run();
