<?

namespace Shop\Modules\AdminOrders;

use Core\Registry\Column;
use Core\Registry\Field;
use Core\Registry\Control;

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

    protected $tableFactory;
    protected $cBuilder;
    protected $repo;
    protected $confMain;
    protected $stateRepo;
    protected $itemRepo;
    protected $transRepo;
    protected $orderService;
    
    use \Shop\Modules\Traits\FormatterTrait;

    function __construct(\Diamond\Factory\Table $tableFactory, \Core\Form\ControlBuilder $builder,
                         \Shop\Repositories\Order $orderRepo, \Shop\Config\Main $confMain,
                         \Shop\Repositories\State $stateRepo, \Shop\Repositories\OrderItem $itemRepo,
                         \Shop\Repositories\PaymasterTransaction $transRepo, \Shop\Services\Order $orderService)
    {
        $this->tableFactory = $tableFactory;
        $this->cBuilder = $builder;
        $this->repo = $orderRepo;
        $this->confMain = $confMain;
        $this->stateRepo = $stateRepo;
        $this->itemRepo = $itemRepo;
        $this->transRepo = $transRepo;
        $this->orderService = $orderService;
    }

    /**
     * 
     * @return type
     */
    protected function buildMergerButton()
    {
        return (new Control\ButtonMultiselectAction("merge_orders", "Объеденить заказы"))
                        ->setMessageNotSelect("Выберите заказы для объединения.")
                        ->setMessageConfirm("Это действие необратимо. Объеденить отмеченные заказы?")
        ;
    }

    /**
     * 
     * @return type
     */
    public function process()
    {

        $builder = $this->cBuilder;

        $states = \Shop\Helpers\Form::prepareDropdown($this->stateRepo);

        $table = $this
                ->tableFactory
                ->buildAdminTable("orders", $this->repo->setSelectFilter([$this, "selectFilter"]))
                ->removeControls(["button_add", "button_edit", "button_del"])
                ->addControl((new Control\ButtonEdit("Просмотр"))->setName("button_view"))
                ->addControl($this->buildMergerButton())
                ->addControl((new Control\ButtonDelete("Удалить"))->setName("button_del"))
                ->setMultiselect(true)
        ;

        if (input_post("merge_orders_ids")) {
            return $this->actionMergeOrders(explode(",", input_post("merge_orders_ids")), $table->getForm());
        }

        $table->getForm()->addValidationPrepareEvent([$this, "actionPrepareData"]);
        $table->getForm()->addValidationSuccessEvent([$this, "actionSendNotifyAfterUpdate"]);
        $table->getForm()->setNewLinkInSuccess(false);

        $table
                ->addColumn(new Column("id", "№", 20, true, true))
                ->addColumn((new Column("code", "Код Заказа", 50))->setFn($this, "formatCode"))
                ->addColumn((new Column("datetime", "Дата заказа", 60))->setFn($this, "formatDate"))
                ->addColumn((new Column("customerId", "Клиент/Группа клиента", 150))->setFn($this, "formatCustomer"))
               // ->addColumn(new Column("delivery_address", "Адрес доставки", 120))
                ->addColumn((new Column("paymentId", "Способ оплаты", 90))->setFn($this, "formatPayment"))
                ->addColumn(new Column("postCode", "Почтовый код", 60))
                ->addColumn((new Column("shopId", "Офис", 120))->setFn($this, "formatShop"))
                ->addColumn((new Column("ItemsCount", "Товаров", 40))->setFn($this, "formatItemsCount"))
                ->addColumn((new Column("discount", "Скидка," . $this->confMain->getCurencyDisplay(), 50))
                        ->setFn($this,"formatDiscount"))
                ->addColumn((new Column("summ", "Сумма итого," . $this->confMain->getCurencyDisplay(), 50))
                        ->setFn($this,"formatSumm"))
                ->addColumn((new Column("stateId", "Состояние", 70))->setFn($this, "formatState"))
        ;

        $table
                ->addField(
                        new Field($builder->buildTextLabel("code")->setFn($this, "formatCode"))
                )
                ->addField(
                        new Field($builder->buildTextLabel("datetime")->setFn($this, "formatDate"))
                )
                ->addField(
                        new Field($builder->buildTextLabel("customerId")->setFn($this, "formatClientFull"))
                )
                ->addField(
                        new Field($builder->buildTextLabel("manager")->setFn($this, "formatManager"),"Информация о менеджере")
                )
                ->addField(
                        new Field($builder->buildTextLabel("deliveryAddress"),"Адрес доставки")
                )
                ->addField(
                        new Field($builder->buildTextLabel("paymentId")->setFn($this, "formatPayment"))
                )
                ->addField(
                        new Field($builder->buildTextLabel("summOrder")->setFn($this, "formatSummOrder"),"Сумма заказа,".$this->confMain->getCurencyDisplay())
                )
                ->addField(
                        new Field($builder->buildTextLabel("discount")->setFn($this, "formatDiscount"))
                )                
                ->addField(
                        new Field($builder->buildTextLabel("summ")->setFn($this, "formatSumm"))
                )

                ->addField(
                        new Field($builder->buildTextArea("comment","-"), "Комментарий клиента")
                )
                ->addField(
                        new Field($builder->buildDropdownUniform("stateId", $states))
                )
                ->addField(
                        new Field($builder->buildInputSmall("postCode"), null, null,
                                                            "Для отслеживания почтовых отправлений")
                )
                ->addHeader("СОДЕРЖИМОЕ ЗАКАЗА")
                ->addField(
                        new Field($builder->buildRow("positions", null)->setFn($this, "formatPositionTable"))
                )
        ;

        return $table->render();
    }

    /**
     * 
     * @param \Shop\Models\Order\Order $order
     * @return string
     */
    public function formatPositionTable(\Shop\Models\Order\Order $order)
    {
        $table = $this
                ->tableFactory
                ->buildSimpleRepoTable("positions", $this->itemRepo->setSelectFilter([$this, "filterByOrder"]))
                ->setBottomPanel(false)
                ->setLimit(9999)
        ;

        $cur = $this->confMain->getCurencyDisplay();

        $table
                ->addColumn((new \Core\Table\Column("num", "№", 20, false, true))->setFn($this, "formatNum"))
                ->addColumn(new \Core\Table\Column("name", "Наименование", 120))
                ->addColumn(new \Core\Table\Column("article", "Артикул", 60))
                ->addColumn(new \Core\Table\Column("brand", "Производитель", 60))
                ->addColumn(new \Core\Table\Column("desc", "Характеристики", 120))
                ->addColumn(new \Core\Table\Column("menagerComment", "Комментарий менеджера", 120))
                ->addColumn(new \Core\Table\Column("price", "Цена," . $cur, 60))
                ->addColumn(new \Core\Table\Column("amount", "Кол-во", 60))
                ->addColumn((new \Core\Table\Column("summ", "Сумма," . $cur, 60))->setFn($this, "formatItemSumm")->setSumm(true))
        ;


        return $table->render();
    }
    private $num = 0;
    
    public function formatNum(\Shop\Models\OrderItem\OrderItem $item)
    {
        $this->num++;
        return $this->num;
    }

    /**
     * 
     * @param \Shop\Models\Order\Order $order
     */
    public function formatCode(\Shop\Models\Order\Order $order)
    {
        return $order->getOrderCode();
    }
    
    /**
     * 
     * @param \Shop\Models\Order\Order $order
     */
    public function formatShop(\Shop\Models\Order\Order $order)
    {
        return $order->getCustomer()->getManager()->getShop()->getTitle();
    }    

    /**
     * 
     * @param \Shop\Models\Order\Order $order
     * @return string
     */
    public function formatDate(\Shop\Models\Order\Order $order)
    {
        return $order->getDatetime(\Diamond\Helpers\Date::formatDisplay());
    }



    /**
     * 
     * @param \Shop\Models\Order\Order $order
     * @return type
     */
    public function formatClientFull(\Shop\Models\Order\Order $order)
    {
        return sprintf("%s,<br/>email: %s,<br/>телефон: %s,<br/>группа: %s",
                       $order->getCustomer()->getName(), 
                       $order->getCustomer()->getEmail(),
                       $order->getCustomer()->getPhone(),
                       $order->getCustomer()->getCustomerGroup()->getName()
        );
    }
    
    /**
     * 
     * @param \Shop\Models\Order\Order $order
     * @return type
     */
    public function formatManager(\Shop\Models\Order\Order $order)
    {
        $manager = $order->getCustomer()->getManager();
        return sprintf("менеджер: %s [%s],<br/>офис: %s",
                       $manager->getName(), $manager->getEmail(),
                       $manager->getShop()->getTitleWithType()
        );
    }    

    /**
     * 
     * @param \Shop\Models\Order\Order $order
     * @return type
     */
    public function formatPayment(\Shop\Models\Order\Order $order): string
    {
        $res = "";

        if ($trans = $this->transRepo->findByOrderId($order->getId())) {
            $res = '<img title="Оплачен" src="/assets/images/payment.gif" />';
        }

        return $res . $order->getPayment()->getTitle();
    }

    /**
     * 
     * @param \Shop\Models\Order\Order $order
     * @return int
     */
    public function formatItemsCount(\Shop\Models\Order\Order $order): int
    {
        return $order->getItemsCount();
    }

    /**
     * 
     * @param \Shop\Models\Order\Order $order
     * @return int
     */
    public function formatSumm(\Shop\Models\Order\Order $order)
    {
        return "<b>". \Shop\Helpers\Price::format($order->getOrderFinalSumm())."</b>";
    }
    
    /**
     * 
     * @param \Shop\Models\Order\Order $order
     * @return type
     */
    public function formatSummOrder(\Shop\Models\Order\Order $order)
    {
        return \Shop\Helpers\Price::format($order->getSumm());
    }    
    
    /**
     * 
     * @param \Shop\Models\Order\Order $order
     * @return int
     */
    public function formatDiscount(\Shop\Models\Order\Order $order)
    {
        return sprintf(
                "%s (%s)",
                \Shop\Helpers\Price::format($order->getDiscountSumm()),
                $order->getDiscountPercent().'%'
                );
    }    

    /**
     * 
     * @param \Shop\Models\Order\Order $order
     * @return int
     */
    public function formatState(\Shop\Models\Order\Order $order): string
    {
        return \Shop\Helpers\State::formatColor($order->getState());
    }

    /**
     * 
     * @param \Shop\Models\Order\OrderQuery $query
     * @return \Shop\Models\Order\OrderQuery
     */
    public function selectFilter(\Shop\Models\Order\OrderQuery $query)
    {
        return $query->orderByDatetime(\Propel\Runtime\ActiveQuery\Criteria::DESC);
    }

    /**
     * 
     * @param \Shop\Models\Position\PositionQuery $query
     * @return \Shop\Models\Position\PositionQuery
     */
    public function filterByOrder(\Shop\Models\OrderItem\OrderItemQuery $query)
    {
        return $query->filterByOrderId(input_get("id"));
    }

    /**
     * 
     * @param \Shop\Models\OrderItem\OrderItem $item
     */
    public function formatItemSumm(\Shop\Models\OrderItem\OrderItem $item)
    {
        return \Shop\Helpers\Price::format($item->getSumm());
    }

    /**
     * prepare data
     * @param array $data
     */
    public function actionPrepareData(array $data, \Core\Form\RepoForm $form)
    {
        $data['old_state'] = $form->getEntity()->getStateId();
        $data['old_post_code'] = $form->getEntity()->getPostCode();
        return $data;
    }

    /**
     * Событие после обновления
     * @param type $data
     * @param type $form
     * @return boolean
     */
    public function actionSendNotifyAfterUpdate(array $data, \Core\Form\RepoForm $form)
    {
        $changeState = $data["old_state"] != $data["stateId"];
        $changePostCode = $data["old_post_code"] != $data["postCode"];

        //создание отчета о смене состояния
        if ($changeState === true) {

            $log = new \Shop\Models\StateLog\StateLog;
            $log
                    ->setNewStateId($data["stateId"])
                    ->setOldStateId($data["old_state"])
                    ->setObjectId($form->getEntity()->getId())
                    ->setTypeId(1)
            ;
            $log->save();
        }

       

        try {

            //если произведена смена состояния и почтового кода, отправляем комплесное уведомление клиенту о состоянии заказа
            if ($changePostCode === true && $changeState === true) {
                $this->orderService->notifyAboutStateAndPostCode($form->getEntity());
            }
            //если произведенеа только смена состояния уведомление клиенту
            elseif ($changeState === true) {
                $this->orderService->notifyAboutState($form->getEntity());
            }
            //если произведена только изменение почт.кода то уведомление клиенту
            elseif ($changePostCode === true) {
                $this->orderService->notifyAboutPostCode($form->getEntity());
            }
        } catch (\Shop\Exceptions\NotifySendError $ex) {

            $form->addBuffer(
                    $form->createMessage($ex->getMessage(), \Core\Form\RepoForm::MESSAGE_ERROR)
            );
        } catch (\Shop\Exceptions\NotifySend $ex) {

            $form->addBuffer(
                    $form->createMessage($ex->getMessage(), \Core\Form\RepoForm::MESSAGE_INFO)
            );
        } catch (\RuntimeException $ex) {

            $this->logger->error($ex->getMessage());

            $form->addBuffer(
                    $form->createMessage("При отправке сообщения возникла ошибка", \Core\Form\RepoForm::MESSAGE_ERROR)
            );
        }
        return true;
    }

    /**
     * 
     * @param type $ids
     * @param type $form
     */
    public function actionMergeOrders(array $ids, \Core\Form\RepoForm $form)
    {

        $back = $form->createReturnLink();

        if (count($ids) < 2) {
            return $form->createMessage("Не выбранны заказы для объединения. " . $back);
        }

        $orders = $this->repo->findByIds($ids);

        $clients_arr = $pay_arr = $state_arr = [];
        foreach ($orders as $order) {
            $clients_arr[$order->getCustomerId()] = $order->getId();
            $pay_arr[$order->getPaymentId()] = $order->getId();
            $state_arr[] = $order->getStateId();
        }


        if (count($clients_arr) > 1) {
            return $form->createMessage('Заказы должны принадлежать одному покупателю. ' . $back);
        }

        if (count($pay_arr) > 1) {
            return $form->createMessage('Заказы должны быть одной системы оплаты. ' . $back);
        }

        if (max($state_arr) > 1) {
            return $form->createMessage('Заказы должны иметь состояние - "Новый". ' . $back);
        }

        $minOrderId = min($ids);
        $otherOrderId = $ids;
        unset($otherOrderId[array_search($minOrderId, $otherOrderId)]);

        if ($this->itemRepo->buildQuery()
                ->filterByOrderId($otherOrderId)
                ->update(["OrderId" => $minOrderId])) {

            if($this->repo->buildQuery()
                    ->filterByPrimaryKeys($otherOrderId)
                    ->delete()){
                        return $form->createMessage(sprintf('Заказы %s успешно объединены c заказом %s ', implode(', ', $otherOrderId), $minOrderId) .nbs(). $back, \Core\Form\Simpleform::MESSAGE_SUCCESS);
                    }
                    else{
                         return $form->createMessage('Заказы объединены, но не удалось удалить освободившиеся заказы. '. $back);
                    }
        }
        return $form->createMessage('Не удалось объеденить заказы. '. $back, \Core\Form\Simpleform::MESSAGE_ERROR);;
    }

}