<?php

// ##############################################################
use KupShop\KupShopBundle\Context\ContextManager;
use KupShop\KupShopBundle\Context\VatContext;
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
use KupShop\KupShopBundle\Util\Contexts;
use KupShop\KupShopBundle\Wrapper\PriceLevelWrapper;
use KupShop\OrderingBundle\Event\OrderEvent;
use KupShop\OrderingBundle\Util\Order\OrderItemEditTrait;
use Query\Operator;

$main_class = 'OrderItems';

class OrderItems extends Frame
{
    use DatabaseCommunication;
    use OrderItemEditTrait;

    protected $template = 'window/orders.items.tpl';
    protected $price_level;

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

        $IDo = getVal('IDo');
        $data = getVal('data', null, []);

        if (!empty($IDo) && !empty($data)) {
            $this->checkStorno($IDo);

            $saved = $this->saveItems($data, $IDo);

            $this->savedPostProcess($saved, $IDo);
        }
    }

    protected function checkStorno($IDo)
    {
        // kontrola jestli objednavka nebyla stornovana
        $storno = ReturnSQLResult('SELECT status_storno
                        FROM '.getTableName('orders')."
                        WHERE id='".$IDo."' ");
        if (intval($storno) == 1) {
            // Stornovanou objednávku již nelze upravovat
            $ErrStr = getTextString('orders', 'errorCanceledCantEdit');
            redirect('launch.php?s=orderItems.php&acn=edititems&IDo='.$IDo.'&ErrStr='.urlencode($ErrStr));
        }
    }

    protected function saveItems($data, $IDo): bool
    {
        $order = new Order($IDo);
        $order->createFromDB($order->id);
        $contextManager = ServiceContainer::getService(ContextManager::class);
        $ret = true;
        try {
            $contextManager->activateOrder($order,
                function () use ($IDo, $data, &$ret) {
                    sqlGetConnection()->transactional(
                        function () use ($IDo, $data, &$ret) {
                            foreach ($data['items'] as $item) {
                                if (!empty($item['id_product'])) {
                                    $ret &= $this->editItem($IDo, $item, (!empty($data['items_discount'])) ? $this->preparePrice($data['items_discount']) : null);
                                }
                            }
                            foreach ($data['discounts'] as $item) {
                                $ret &= $this->editItem($IDo, $item);
                            }
                            if ($ret) {
                                sqlQuery("UPDATE orders SET date_updated=NOW() WHERE id='{$IDo}' ");

                                // Recalculate order
                                $order = new Order($IDo);
                                $order->createFromDB($order->id);

                                $eventDispatcher = ServiceContainer::getService('event_dispatcher');
                                $event = new OrderEvent($order);
                                $eventDispatcher->dispatch($event, OrderEvent::ORDER_EDITED);

                                $order->recalculate();

                                $code = returnSQLResult("SELECT order_no FROM orders WHERE id='{$IDo}' ");
                                writeDownActivity(sprintf(getTextString('orders', 'activityItemEdited'), $code));
                            }
                        }
                    );
                }
            );
        } catch (Exception $ex) {
            $this->addHTMLError($ex->getMessage());

            return false;
        }

        return $ret;
    }

    protected function savedPostProcess($saved, $IDo)
    {
        if ($saved) {
            // Položka byla upravena
            $ErrStr = getTextString('status', 'saved');
            $this->returnOK($ErrStr);
        } else {
            if ($this->getHTMLErrors()) {
                // Exception in saveItems
                return false;
            }
            // Chyba při ukládání do databáze
            $ErrStr = getTextString('status', 'scripterror');
            $this->returnError($ErrStr, '', $IDo);
        }
    }

    protected function getItemsOrdering()
    {
        return 'oi.id';
    }

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

        $ID = getVal('IDo');

        $pageVars = [];
        $pageVars['acn'] = getVal('acn');
        $pageVars['id'] = $ID;

        $order = new Order();
        $order->createFromDB($ID, false, true, true);

        $currencyContext = ServiceContainer::getService(\KupShop\KupShopBundle\Context\CurrencyContext::class);
        $currencyContext->activate($order->currency ?? 'CZK');

        $pageVars['order'] = $order;

        $contextManager = ServiceContainer::getService(ContextManager::class);
        $pageVars['defaultVat'] = $contextManager->activateOrder($order, function () {
            $vatContext = Contexts::get(VatContext::class);

            return $vatContext->getDefault()['vat'];
        });

        // Vats
        foreach (\KupShop\KupShopBundle\Context\VatContext::getAdminVats(true) as $row) {
            $pageVars['vats'][(string) $row['vat']] = "{$row['vat']} %";
        }

        $fields = '';

        if (findModule('products_variations', 'variationCode')) {
            $fields .= ', COALESCE(pv.code, p.code) code';
        } else {
            $fields .= ', p.code code';
        }

        $SQL = sqlQuery("SELECT oi.*, COALESCE(pv.in_store, p.in_store) in_store, COALESCE(pv.ean, p.ean) ean, pv.title variation_title {$fields}
               FROM order_items oi
               LEFT JOIN products_variations pv ON pv.id=oi.id_variation
               LEFT JOIN products p ON p.id=oi.id_product
               WHERE oi.id_order={$ID} AND oi.id_product >= 0
               ORDER BY {$this->getItemsOrdering()}");

        $pageVars['total_price'] = toDecimal(0);
        $pageVars['total_price_vat'] = toDecimal(0);

        $p = new Product();

        foreach ($SQL as $row) {
            $row['pieces'] = floatval($row['pieces']);
            $row['in_store'] = floatval($row['in_store']);
            if ($row['in_store'] < 0) {
                if ($row['id_product']) {
                    // Currently ordered offset
                    $query = 'SELECT SUM(oi.pieces)
								FROM '.getTableName('order_items').' oi
								LEFT JOIN '.getTableName('orders').' o ON oi.id_order=o.id,
								'.getTableName('orders')." o2
								WHERE o2.id={$ID} AND o.date_created >= o2.date_created AND oi.id_product={$row['id_product']}
								AND o.status_storno=0 AND o.id!={$ID} AND o.status IN (".join(',', getStatuses('active')).')';
                    if (!empty($row['id_variation'])) {
                        $query .= "AND oi.id_variation={$row['id_variation']}";
                    }
                    $row['piecesOrdered'] = returnSQLResult($query);

                    // Suppliers products
                    if (findModule('products_suppliers')) {
                        $query = 'SELECT SUM(in_store)
										FROM '.getTableName('products_of_suppliers')." pos
										WHERE pos.id_product={$row['id_product']}";

                        if (!empty($row['id_variation'])) {
                            $query .= " AND pos.id_variation={$row['id_variation']}";
                        }

                        $row['piecesInSuppliers'] = returnSQLResult($query);
                    }
                }
            }

            $row['piece_price'] = toDecimal($row['piece_price']);

            $row['discount'] = toDecimal(getVal('discount', $row, 0));

            $row['total_price'] = toDecimal($row['total_price']);
            $row['piece_price_vat'] = $row['piece_price']->addVat($row['tax'])->value(2);
            $row['total_price_vat'] = $row['total_price']->addVat($row['tax'])->value(2);
            $pageVars['total_price'] = $pageVars['total_price']->add(toDecimal($row['total_price']));
            $pageVars['total_price_vat'] = $pageVars['total_price_vat']->add(toDecimal($row['total_price_vat']));

            $row['custom_data'] = $p->parseNote($row['note']);
            $row['note'] = $p->printNote($p->parseNote($row['note']));

            $pageVars['pv'][] = $row;
        }

        $SQL = sqlQuery('SELECT *
               FROM '.getTableName('order_items')."
               WHERE id_order={$ID} AND id_product IS NULL
               ORDER BY id ASC");

        foreach ($SQL as $row) {
            $row['pieces'] = floatval($row['pieces']);
            $row['discount'] = toDecimal(getVal('discount', $row, 0));

            $row['piece_price'] = toDecimal($row['piece_price']);
            $row['total_price'] = toDecimal($row['total_price']);
            $row['piece_price_vat'] = $row['piece_price']->addVat($row['tax'])->value(2);
            $row['total_price_vat'] = $row['total_price']->addVat($row['tax'])->value(2);
            $pageVars['total_price'] = $pageVars['total_price']->add(toDecimal($row['total_price']));
            $pageVars['total_price_vat'] = $pageVars['total_price_vat']->add(toDecimal($row['total_price_vat']));

            $row['custom_data'] = $p->parseNote($row['note']);
            $row['note'] = $p->printNote($p->parseNote($row['note']));
            $pageVars['oi'][] = $row;
        }

        if (findModule('price_levels')) {
            if ($pl = $order->getOrderPriceLevel()) {
                $pageVars['price_level'] = PriceLevelWrapper::wrap($pl);
            }
        }

        $vars['body'] = $pageVars;

        if (findModule(Modules::WAREHOUSE)) {
            $warehouse_order = sqlQueryBuilder()->select('1')->from('warehouse_orders')
                                ->where(Operator::equals(['id_order' => $ID]))
                                ->andWhere('date_close IS NOT NULL AND id_position IS NULL')
                                ->execute()->fetch();

            if (!empty($warehouse_order) && !findRight('WAR_ORDER_EDIT')) {
                $vars['warehouse_closed'] = true;
            }
        }

        return $vars;
    }
}
