<?php

namespace KupShop\ReclamationsElninoBundle\View;

use KupShop\KupShopBundle\Context\UserContext;
use KupShop\KupShopBundle\Exception\RedirectException;
use KupShop\KupShopBundle\Util\Database\QueryHint;
use KupShop\KupShopBundle\Views\View;
use KupShop\ReclamationsElninoBundle\Util\ReclamationsUtil;
use Query\Operator;
use Symfony\Component\HttpFoundation\Session\SessionInterface;

class CreateReclamationView extends View
{
    protected static $type = 'reclamations';

    protected $template = 'reclamations/reclamations-new.products.tpl';
    protected static $tableName = 'reclamations_elnino';

    private $session;

    private $step = 'orders';
    private $itemId;
    private $orderId;

    private $reclamationsUtil;
    private $userContext;

    private \Pager $pager;

    public function __construct(ReclamationsUtil $reclamationsUtil, UserContext $userContext, SessionInterface $session)
    {
        $this->reclamationsUtil = $reclamationsUtil;
        $this->userContext = $userContext;
        $this->session = $session;
        $this->setPager(new \Pager());
    }

    public function getBodyVariables()
    {
        $vars = parent::getBodyVariables();
        $page = getVal('page', null, 1);
        $noOnPage = 50;
        $pager = $this->getPager();
        $pager->setOnPage($noOnPage);
        $pager->setPageNumber($page);

        $vars['items'] = $items = $this->getBoughtItems();

        if ($this->orderId) {
            $this->session->set('reclamation_items', []);
            $this->session->set('reclamation_selected_items', []);
        }

        $this->setItemId($this->session->get('reclamation_selected_items'));

        if ($this->step == 'summary' && $this->itemId) {
            foreach ($this->itemId as $orderItem) {
                $itemExists = false;
                foreach ($items as $item) {
                    if ($item['id'] == $orderItem && !$item['expired']) {
                        $itemExists = true;
                        break;
                    }
                }
                if (!$itemExists) {
                    break;
                }
            }

            if (!$itemExists) {
                $this->addErrorMessage(translate('error_item', 'reclamations'));
                throw new RedirectException(path('kupshop_reclamationselnino_reclamations_createreclamation'));
            }

            $orderId = sqlQueryBuilder()->select('id_order')
               ->from('order_items')->where(Operator::equals(['id' => $orderItem]))
               ->execute()->fetchColumn();

            if ($orderId) {
                $order = new \Order();
                $order->createFromDB($orderId);

                $vars['order'] = $order;
            }

            $vars['preferred_handle_types'] = $this->reclamationsUtil->getPrefHandleTypes();
        } else {
            $vars['itemsInOrder'] = [];
            $vars['orderSelected'] = null;

            foreach ($items as $item) {
                if (empty($vars['itemsInOrder'][$item['id_order']][$item['id']])) {
                    $vars['itemsInOrder'][$item['id_order']][$item['id']] = $item;
                }

                $vars['allItemsSelected'][$item['id_order']] = true;
                if ($item['selected'] == false) {
                    $vars['allItemsSelected'][$item['id_order']] = false;
                }

                if ($this->orderId) {
                    $vars['orderSelected'] = $this->orderId;
                } elseif ($item['selected'] == true) {
                    $vars['orderSelected'] = $item['id_order'];
                }
            }

            $vars['reclamation_items'] = $this->session->get('reclamation_items');
        }

        return $vars;
    }

    public function handleStep_products($items, $reclamation_items)
    {
        if (empty($items)) {
            $this->returnNoItemsError();
        }
        $reclamationItems = [];
        foreach ($items as $item) {
            $reclamationItems[$item] = $reclamation_items[$item];
        }
        $this->session->set('reclamation_form_data', null);
        $this->session->set('reclamation_selected_items', $items);
        $this->session->set('reclamation_items', $reclamationItems);

        throw new RedirectException(path('kupshop_reclamationselnino_reclamations_createreclamationsummary'));
    }

    public function handleStep_reclamationSummary($delivery, $bankAccount, $preferred_handle_type, $note, $user_content)
    {
        $items = $this->session->get('reclamation_items');

        if (empty($items)) {
            $this->returnNoItemsError();
        }

        // validate required address fields
        foreach ($this->reclamationsUtil->getAddressFields() as $field) {
            if (empty($delivery[$field])) {
                addUserMessage(translate('error_delivery_fields', 'reclamations'), 'danger');
                throw new RedirectException(path('kupshop_reclamationselnino_reclamations_createreclamationsummary'));
            }
        }

        if (empty($note)) {
            addUserMessage(translate('error_note', 'reclamations'), 'danger');
            throw new RedirectException(path('kupshop_reclamationselnino_reclamations_createreclamationsummary'));
        }

        if ($id = QueryHint::withRouteToMaster(function () use ($items, $delivery, $bankAccount, $preferred_handle_type, $note, $user_content) {
            return $this->reclamationsUtil->createReclamation($items, 1, $delivery, $bankAccount, $preferred_handle_type, $note, true, $user_content);
        })) {
            $this->session->set('reclamation_items', []);
            $this->session->set('reclamation_selected_items', []);
            throw new RedirectException(path('kupshop_reclamations_reclamations_reclamation', ['id' => $id, 'success' => 1]));
        }
    }

    private function getBoughtItems()
    {
        $qb = sqlQueryBuilder()
           ->select('id_item, id_reclamation, COALESCE(SUM(pieces), 0) as pieces')
           ->from('reclamation_items_elnino');

        $products = sqlQueryBuilder()
            ->select('oi.*, COALESCE(o.date_handle, o.date_created) as delivery_date, (oi.pieces - COALESCE(rie.pieces, 0)) as returnable_pieces, p.guarantee, o.order_no')
            ->from('order_items', 'oi')
            ->leftJoin('oi', 'orders', 'o', 'o.id = oi.id_order')
            ->leftJoin('oi', "({$qb})", 'rie', 'oi.id = rie.id_item')
            ->leftJoin('oi', self::$tableName, 'r', 'r.id = rie.id_reclamation AND r.status != '.ReclamationsUtil::STATUS_HANDLED)
            ->leftJoin('oi', 'products', 'p', 'p.id = oi.id_product')
            ->andWhere('oi.id_product IS NOT NULL')
            ->andWhere(Operator::inIntArray(getStatuses('handled'), 'o.status'))
            ->andWhere('o.status_storno != 1')
            ->andWhere($this->reclamationsUtil->getOrdersSpec())
            ->orderBy('delivery_date', 'DESC')
            ->groupBy('oi.id');

        if (findModule(\Modules::RETURNS)) {
            $products
                ->addSelect('(oi.pieces - COALESCE(SUM(rie.pieces), 0) - COALESCE(SUM(ri.pieces), 0)) as returnable_pieces')
                ->leftJoin('oi', 'return_items', 'ri', 'oi.id = ri.id_item');
        }
        $products
            ->addSelect($this->reclamationsUtil->getExpiredItemsSpec())
            ->addCalcRows();

        if ($this->step == 'products') {
            $products->andWhere($this->getPager()->getSpec());
        }

        $counts = $this->session->get('reclamation_items', []);
        $usedItemsCount = [];

        $return = [];
        $productsList = $products->execute();
        $this->getPager()->setTotal(returnSQLResult('SELECT FOUND_ROWS()'));
        foreach ($productsList as $item) {
            $piecePrice = toDecimal($item['piece_price']);
            $piecePrice = $piecePrice->addVat($item['tax']);

            $item['piece_price_with_vat'] = $piecePrice;

            for ($i = 0; $i < $item['returnable_pieces']; $i++) {
                if (!isset($usedItemsCount[$item['id']])) {
                    $usedItemsCount[$item['id']] = 1;
                } else {
                    $usedItemsCount[$item['id']]++;
                }

                if (isset($counts[$item['id']]) && $usedItemsCount[$item['id']] <= $counts[$item['id']]) {
                    $item['selected'] = true;
                } else {
                    $item['selected'] = false;
                }

                $return[] = $item;
            }
        }

        return $return;
    }

    public function getBreadcrumbs()
    {
        return getReturnNavigation(-1, 'RECLAMATION', [$this->getTitle()]);
    }

    public function getTitle()
    {
        return translate('create_reclamation_title', 'reclamations');
    }

    public function setItemId($itemId)
    {
        $this->itemId = $itemId;

        return $this;
    }

    public function setOrderId($orderId)
    {
        $this->orderId = $orderId;

        return $this;
    }

    public function setStep($step)
    {
        $this->step = $step;

        return $this;
    }

    private function returnNoItemsError()
    {
        addUserMessage(translate('error_no_items', 'reclamations'), 'danger');
        throw new RedirectException(path('kupshop_reclamationselnino_reclamations_createreclamation'));
    }

    public function getTemplate()
    {
        switch ($this->step) {
            case 'products':
                return 'reclamations/reclamations-new.products.tpl';
            case 'summary':
                return 'reclamations/reclamations-new.summary.tpl';
        }

        return $this->template;
    }

    private function getPager(): \Pager
    {
        return $this->pager;
    }

    private function setPager(\Pager $pager): void
    {
        $this->pager = $pager;
    }
}
