<?php

namespace Shop\Presentation\Modules\AdminOrders;

use ActiveTable\ColumnTable;
use ActiveTable\DataTableEngine;
use Core\Form\ControlBuilder;
use Diamond\Application\Notification\Exceptions\NotificationException;
use Diamond\Helpers\Form;
use DiamondTable\CommandFactory;
use DiamondTable\Commands\CustomClosureCommand;
use DiamondTable\Commands\CustomCommand;
use DiamondTable\TableFactory;
use Shop\Application\Shopping\ShoppingService;
use Shop\Presentation\Config\Main;
use Shop\Domain\OrderItem\Contracts\OrderItemEntityInterface;
use Shop\Infrastructure\Models\Order\Order;
use Shop\Presentation\Modules\Traits\FormatterTrait;
use Shop\Infrastructure\Repositories\CustomerOrder\CustomerOrderCriteria;
use Shop\Infrastructure\Repositories\CustomerOrder\CustomerOrderRepository;
use Shop\Infrastructure\Repositories\OrderItem\OrderItemCriteria;
use Shop\Infrastructure\Repositories\OrderItem\OrderItemRepository;
use Shop\Infrastructure\Repositories\State\StateCriteria;
use Shop\Infrastructure\Repositories\State\StateRepository;
use Shop\Infrastructure\Repositories\Stock\StockCriteria;
use Shop\Infrastructure\Repositories\Stock\StockRepository;
use Shop\Application\Shopping\ShoppingService as Checkout;
use function Clue\StreamFilter\fun;

/**
 * Description of AdminOrders
 *
 * @author Diamond Code Generator
 */
class AdminOrders extends \Core\ModuleController
{

    use FormatTrait;
    use FormatterTrait;

    public function __construct(protected CustomerOrderRepository $customerOrderRepository,
                                protected TableFactory            $tableFactory,
                                protected ControlBuilder          $controlBuilder,
                                protected Main                    $mainConfig,
                                protected StateRepository         $stateRepository,
                                protected Checkout                $checkoutUseCase,
                                protected StockRepository         $stockRepository,
                                protected ShoppingService $shoppingService,
                                protected OrderItemRepository     $orderItemRepository
    )
    {
    }

    /**
     * @return string
     * @throws \ReflectionException
     * @throws \Repo\Concrete\Exceptions\Collection
     */
    public function process(): string
    {

        $table = $this->tableFactory->buildAdminTable($this->customerOrderRepository, CustomerOrderCriteria::create());

        $table->setCommand(CommandFactory::FORM_AFTER_SAVE, new CustomClosureCommand(function () use ($table) {
            $postData = $table->getRequest()->getParsedBody();
            $this->actionSendNotifyAfterUpdate($postData, $table->getTableRowEntity());
        }));

        $table->removeControlAccess(DataTableEngine::CONTROL_ACCESS_ADD);
        $table->setDefaultSortColumn('id', 'DESC');
        $table->setFormEditText('Изменение заказа №');
        $table->setFormAddText('Создание заказа');

        $states = $this->stateRepository->findByCriteria(
            StateCriteria::create()
        );

        $table
            ->addRowActionCommand(
                'merge-orders-selected',
                new MergeOrdersCommand($this->checkoutUseCase),
                '<i class="fa fa-group"></i> Объеденить заказы'
            )
            ->addRowActionCommand(
                'send-orders-selected',
                new SendNotificationCommand($this->checkoutUseCase),
                '<i class="fa fa-envelope"></i> Отправить клиентам на email'
            )
            ->addRowActionCommand(
                'send-orders-managers-selected',
                new SendNotificationCommand($this->checkoutUseCase, true),
                '<i class="fa fa-envelope"></i> Отправить менеджерам на email'
            );

        $table
            ->addColumn(
                (new ColumnTable('ordercode', 'Код заказа'))
                    ->setFormat($this, 'formatCode')
                    ->setWidth(40)
            )
            ->addColumn(
                (new ColumnTable('datetime', 'Дата заказа'))
                    ->setFormat($this, 'formatDate')

            )
            ->addColumn(
                (new ColumnTable('customerId', 'Клиент'))
                    ->setFormat($this, 'formatCustomer')

            )
            ->addColumn(
                (new ColumnTable('paymentId', 'Способ оплаты'))
                    ->setFormat($this, 'formatPayment')

            )
//            ->addColumn(
//                (new ColumnTable('postCode', 'Почтовый код'))
//
//            )
            ->addColumn(
                (new ColumnTable('stockId', 'Торговая точка'))
                    ->setFormat($this, 'formatShop')

            )
            ->addColumn(
                (new ColumnTable('itemsCount', 'Товаров в заказе'))
                    ->setFormat($this, 'formatItemsCount')

            )
            ->addColumn(
                (new ColumnTable('discount', 'Скидка'))
                    ->setFormat($this, 'formatDiscount')
            )
            ->addColumn(
                (new ColumnTable('sum', 'Сумма итого'))
                    ->setFormat($this, 'formatSumm')
            )
            ->addColumn(
                (new ColumnTable('stateId', 'Состояние'))
                    ->setFormat($this, 'formatStates')

            )
            ->addColumn(
                (new ColumnTable('actions', ''))
                    ->setFormat($this, 'formatActions')
                    ->setWidth(120)
            );

        if (input_get('id')) {
            $orderId = (int)input_get('id');

            $currency = $this->shoppingService->getDefaultCurrency();

            $orderItemsTable =
                (new \Core\Table\PropelDataTable($this->orderItemRepository,
                    OrderItemCriteria::create()->setFilterByOrderIds([$orderId])))
                    ->setClass('nifty-table dataTable  table table-striped');

            $orderItemsTable->setBottomPanel(false);

            $summFormat = function (OrderItemEntityInterface $item) {
                return \Shop\Presentation\Helpers\Price::display($item->getPrice() * $item->getAmount());
            };

            $sizesFormat = function (OrderItemEntityInterface $item) {
                return \Shop\Presentation\Helpers\Price::display($item->getPrice() * $item->getAmount());
            };

            $orderItemsTable->addColumn(new \Core\Table\Column('id', 'Номер позиции'));
            $orderItemsTable->addColumn(new \Core\Table\Column('name', 'Наименование'));
            $orderItemsTable->addColumn(new \Core\Table\Column('article', 'Артикул'));
            $orderItemsTable->addColumn((new \Core\Table\Column('desc', 'Характеристики'))->setFn($sizesFormat));
            $orderItemsTable->addColumn(new \Core\Table\Column('price', 'Цена, ' . $currency));
            $orderItemsTable->addColumn(new \Core\Table\Column('amount', 'Кол-во'));
            $orderItemsTable->addColumn((new \Core\Table\Column('summ', 'Сумма, ' . $currency))->setFn($summFormat));
        }

        $table
            ->startTab('Заказ')
            ->addField(
                $this
                    ->controlBuilder
                    ->buildTextLabel('ordercode')
                    ->setFn($this, 'formatCode')
            )
            ->addField(
                $this
                    ->controlBuilder
                    ->buildTextLabel('datetime')
                    ->setFn($this, 'formatDate')
            )
            ->addField(
                $this
                    ->controlBuilder
                    ->buildTextLabel('sumOrder')
                    ->setFn($this, 'formatSummOrder'),
                false, 'Сумма заказа'
            )
            ->addField(
                $this
                    ->controlBuilder
                    ->buildTextLabel('discount')
                    ->setFn($this, 'formatDiscount')
            )
            ->addField(
                $this
                    ->controlBuilder
                    ->buildTextLabel('sum')
                    ->setFn($this, 'formatSumm')
            )
            ->addField(
                $this
                    ->controlBuilder
                    ->buildFormHeader('Информация о клиенте', 'client')
            )
            ->addField(
                $this
                    ->controlBuilder
                    ->buildTextLabel('customerId')
                    ->setFn($this, 'formatClientFull')
            )
            ->addField(
                $this
                    ->controlBuilder
                    ->buildTextLabel('customerСontacts')
                    ->setFn($this, 'formatClientContacts'),
                false,
                'Контакты'
            )
            ->addField(
                $this
                    ->controlBuilder
                    ->buildTextLabel('deliveryAddress')
                , false, 'Адрес доставки'
            )
            ->addField(
                $this
                    ->controlBuilder
                    ->buildTextLabel('paymentId')
                    ->setFn($this, 'formatPayment')
            )
            ->addField(
                $this
                    ->controlBuilder
                    ->buildFormHeader('Информация о контрагенте', 'stockHeader')
            )
            ->addField(
                $this
                    ->controlBuilder
                    ->buildTextLabel('stockId')
                    ->setFn($this, 'formatStock'),
                false
            )
            ->addField(
                $this
                    ->controlBuilder
                    ->buildTextLabel('manager')
                    ->setFn($this, 'formatManager'),
                false,
                'Менеджер'
            )
            ->addField(
                $this
                    ->controlBuilder
                    ->buildFormHeader('Данные заказа', 'orderInfo')
            )
            ->addField(
                $this
                    ->controlBuilder
                    ->buildTextArea('comment')
                , false, 'Комментарий к заказу'
            )
            ->addField(
                $this
                    ->controlBuilder
                    ->buildDropdownUniform('stateId', Form::prepareDropdown($states))
                , true, 'Состояние заказа'
            )
            ->addField(
                $this
                    ->controlBuilder
                    ->buildInputSmall('postCode')
                , false, 'Почтовый код', 'Для отслеживания почтовых отправлений'
            )
            ->endTab();

        if(isset($orderItemsTable)){

            $table
                ->startTab('Товары')
                ->addField(
                    $this->controlBuilder->buildRow('items', $orderItemsTable->render())
                )
                ->endTab();
        }


        $stocks = $this->stockRepository->findByCriteria(
            StockCriteria::create()->setFilterByActive(true)->setSortByTitle('asc')
        );

        $table
            ->addFilter(
                $this->controlBuilder->buildInput('filter_by_ordercode')
            )
            ->addFilter(
                $this->controlBuilder->buildDropdownUniform('filter_by_stateId',
                    Form::prepareDropdown($states))
            )
            ->addFilter(
                $this->controlBuilder->buildDropdownUniform('filter_by_stockId',
                    Form::prepareDropdown($stocks))
            );

        return $table->render();

    }


    /**
     * Событие после обновления
     * @param type $data
     * @param type $form
     * @return boolean
     */
    public function actionSendNotifyAfterUpdate(array $data, Order $order): void
    {
        $changePostCode = $changeStateId = null;

        if (in_array('shop_orders.post_code', $order->getModifiedColumns(), true) && $order->getPostCode() > '') {
            $changePostCode = $order->getPostCode();
        }

        if (in_array('shop_orders.state_id', $order->getModifiedColumns(), true)) {
            $changeStateId = $order->getStateId();
        }

        //смена состояний позиций заказа
        if ($this->mainConfig->getModeChangeOrderStates() === Main::MODE_CHANGE_STATE_FROM_ORDER && $changeStateId !== null) {
            $this->checkoutUseCase->changeOrderItemsState($order, $changeStateId);
        }

        try {
            //если произведена смена состояния и почтового кода, отправляем комплесное уведомление клиенту о состоянии заказа
            if ($changePostCode !== null && $changeStateId !== null) {
                $this->checkoutUseCase->sendNotifyAboutPostCodeAndState($order);
                \Shop\Presentation\Helpers\Form::addTableNotice(
                    \Shop\Presentation\Helpers\Form::buildSuccessMessage(
                        'Уведомление с почтовым кодом и о смене состояния заказа успешно отправлено клиенту'
                    )
                );
            } //если произведенеа только смена состояния уведомление клиенту
            elseif ($changeStateId !== null) {
                $this->checkoutUseCase->sendNotifyOrderChangeState($order);
                \Shop\Presentation\Helpers\Form::addTableNotice(
                    \Shop\Presentation\Helpers\Form::buildSuccessMessage(
                        'Уведомление о смене состояния заказа успешно отправлено клиенту'
                    )
                );
            } //если произведена только изменение почт.кода то уведомление клиенту
            elseif ($changePostCode !== null) {
                $this->checkoutUseCase->sendNotifyAboutPostCode($order);
                \Shop\Presentation\Helpers\Form::addTableNotice(
                    \Shop\Presentation\Helpers\Form::buildSuccessMessage(
                        'Уведомление с почтовым кодом успешно отправлено клиенту'
                    )
                );
            }
        } catch (NotificationException $ex) {
            $this->logger->error($ex->getMessage());
            \Shop\Presentation\Helpers\Form::addTableNotice(
                \Shop\Presentation\Helpers\Form::buildErrorMessage(
                    'Не удалось отправить сообщение, обратитесь к администратору системы'
                )
            );
        }

    }


}