<?php

namespace Shop\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\Config\Main;
use Shop\Models\Order\Order;
use Shop\Modules\Traits\FormatterTrait;
use Shop\Repositories\CustomerOrder\CustomerOrderCriteria;
use Shop\Repositories\CustomerOrder\CustomerOrderRepository;
use Shop\Repositories\State\StateCriteria;
use Shop\Repositories\State\StateRepository;
use Shop\Repositories\Stock\StockCriteria;
use Shop\Repositories\Stock\StockRepository;
use Shop\Application\Shopping\ShoppingService as Checkout;

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

    use FormatTrait;
    use FormatterTrait;

    protected $customerOrderRepository;
    protected $tableFactory;
    protected $mainConfig;
    protected $stateRepository;
    protected $checkoutUseCase;
    protected $stockRepository;

    public function __construct(CustomerOrderRepository $customerOrderRepository,
                                TableFactory $tableFactory, ControlBuilder $controlBuilder,
                                Main $mainConfig,
                                StateRepository $stateRepository, Checkout $checkoutUseCase,
                                StockRepository $stockRepository
    )
    {
        $this->customerOrderRepository = $customerOrderRepository;
        $this->tableFactory = $tableFactory;
        $this->controlBuilder = $controlBuilder;
        $this->mainConfig = $mainConfig;
        $this->stateRepository = $stateRepository;
        $this->checkoutUseCase = $checkoutUseCase;
        $this->stockRepository = $stockRepository;
    }

    /**
     * @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');

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

        $table
            ->addRowActionCommand(
                'merge-orders-selected',
                new MergeOrdersCommand($this->checkoutUseCase),
                'Объеденить заказы'
            )
            ->addRowActionCommand(
                'send-orders-selected',
                new SendNotificationCommand($this->checkoutUseCase),
                'Отправить клиентам на email'
            )
            ->addRowActionCommand(
                'send-orders-managers-selected',
                new SendNotificationCommand($this->checkoutUseCase,true),
                'Отправить менеджерам на 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)
            );

        $table
            ->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,'Почтовый код','Для отслеживания почтовых отправлений'
            )
        ;

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

    }


}