<?php

namespace Shop\Modules\AdminShopManagers;

use ActiveTable\ColumnTable;
use Core\Form\ControlBuilder;
use Core\Form\FormBuilder;
use Core\Form\Simpleform;
use Core\Helpers\Text;
use Diamond\Helpers\Form;
use Diamond\Repositories\User\UserCriteria;
use Diamond\Repositories\User\UserRepository;
use Diamond\Repositories\UserGroup\UserGroupCriteria;
use Diamond\Repositories\UserGroup\UserGroupRepository;
use DiamondTable\CommandFactory;
use DiamondTable\TableFactory;
use Shop\Config\Main;
use Shop\Domain\Manager\Contracts\ManagerEntityInterface;
use Shop\Models\Customer\Customer;
use Shop\Models\Manager\Manager;
use Shop\Modules\AdminShops\MoveCustomersCommand;
use Shop\Repositories\Customer\CustomerCriteria;
use Shop\Repositories\Customer\CustomerRepository;
use Shop\Repositories\CustomerGroup\CustomerGroupCriteria;
use Shop\Repositories\CustomerGroup\CustomerGroupRepository;
use Shop\Repositories\Manager\ManagerCriteria;
use Shop\Repositories\Manager\ManagerRepository;
use Shop\Repositories\Stock\StockCriteria;
use Shop\Repositories\Stock\StockRepository;

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

    protected $customerRepository;
    protected $managerRepository;
    protected $tableFactory;
    protected $controlBuilder;
    protected $stockRepository;
    protected $userRepository;
    protected $userGroupRepository;
    protected $customerGroupRepository;
    protected $mainConf;
    protected $formBuilder;
    protected $customerGroups = [];

    public function __construct(ManagerRepository       $managerRepository, TableFactory $tableFactory,
                                ControlBuilder          $controlBuilder,
                                StockRepository         $stockRepository,
                                UserRepository          $userRepository,
                                UserGroupRepository     $userGroupRepository,
                                CustomerGroupRepository $customerGroupRepository,
                                CustomerRepository      $customerRepository,
                                Main                    $mainConf,
                                FormBuilder             $formBuilder
    )
    {
        $this->managerRepository = $managerRepository;
        $this->tableFactory = $tableFactory;
        $this->stockRepository = $stockRepository;
        $this->controlBuilder = $controlBuilder;
        $this->userRepository = $userRepository;
        $this->userGroupRepository = $userGroupRepository;
        $this->customerRepository = $customerRepository;
        $this->formBuilder = $formBuilder;
        $this->mainConf = $mainConf;
        $this->customerGroupRepository = $customerGroupRepository;
    }


    /**
     * @return string
     * @throws \ReflectionException
     * @throws \Repo\Concrete\Exceptions\Collection
     * @throws \Twig\Error\LoaderError
     * @throws \Twig\Error\RuntimeError
     * @throws \Twig\Error\SyntaxError
     */
    public function process(): string
    {

        $managersAr = $this->managerRepository->findByCriteria(
            ManagerCriteria::create()->setSortByName('ASC')
        );

        $table = $this->tableFactory->buildAdminTable($this->managerRepository, ManagerCriteria::create());
        $table->setDefaultSortColumn('id', 'DESC');
        $table
            ->addRowActionCommand(
                'move-customers-selected',
                new MoveCustomersCommand($table, $this->buildMoveCustomersForm(Form::prepareDropdown($managersAr, 'манеджер', 'getDropdownListWithShop')),
                    $this->customerRepository),
                'Перенос клиентов'
            );

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

        $userGroups = $this->userGroupRepository->findByCriteria(
            UserGroupCriteria::create()
        );

        $customerGroups = $this->customerGroupRepository->findByCriteria(
            CustomerGroupCriteria::create()
        );

        foreach ($customerGroups as $k => $group) {
            if ($group->getId() !== $this->mainConf->getDefaultContractorGroup()
            ) {
                $this->customerGroups[] = $group->getId();
            }
        }

        $table->setCommand(CommandFactory::FORM_SAVE, new SaveManagerCommand($table, $this->userRepository));
        $table->setCommand(CommandFactory::ROWS_DELETE, new DeleteManagerCommand($table, $this->userRepository, $this->logger));
        $currentUserGroupId = null;
        if (input_get('id') > 0) {
            $manager = $this->managerRepository->findById(input_get('id'));
            if ($manager) {
                $users = $this->userRepository->findByCriteria(
                    UserCriteria::create()->setFilterByEmail($manager->getEmail())
                );
                $user = $users->current();
                if ($user) {
                    $currentUserGroupId = $users->current()->getGroupId();
                }

            }
        }

        $table
            ->addColumn(
                (new ColumnTable('id', '№'))
                    ->setWidth(40)
            )
            ->addColumn(
                (new ColumnTable('name', 'ФИО'))->setWidth(160)
            )
            ->addColumn(
                (new ColumnTable('email', 'Электронная почта'))->setWidth(160)
            )
            ->addColumn(
                (new ColumnTable('phone', 'Телефон'))->setWidth(160)
            )
            ->addColumn(
                (new ColumnTable('comment', 'Комментарий'))
                    ->setFormat($this, 'formatComment')
            )
            ->addColumn(
                (new ColumnTable('stockId', 'Торг.точка'))
                    ->setFormat($this, 'formatShop')
            )
            ->addColumn(
                (new ColumnTable('user', 'Доступ в админ.часть'))
                    ->setFormat($this, 'formatAccess')
            )
            ->addColumn(
                (new ColumnTable('customer', 'Доступ в клиентскую.часть'))
                    ->setFormat($this, 'formatCustomerAccess')
            )
            ->addColumn(
                (new ColumnTable('customer', 'Клиентов'))
                    ->setFormat($this, 'formatCountCustomers')
                    ->setWidth(40)
            )
            ->addColumn(
                (new ColumnTable('actions', ''))
                    ->setFormat($this->tableFactory, 'formatActions')
                    ->setWidth(120)
            );

        $table
            ->addField(
                $this->controlBuilder->buildFormHeader('Основная информация о менеджере', 'main')
            )
            ->addField(
                $this->controlBuilder->buildInput('name'), true
            )
            ->addField(
                $this->controlBuilder->buildInput('email'), true, null, null, ['email']
            )
            ->addField(
                $this->controlBuilder->buildPhoneInput('phone', $this->mainConf->getMobileMask())
            )
            ->addField(
                $this->controlBuilder->buildTextArea('comment')
            )
            ->addField(
                $this->controlBuilder->buildDropdownUniform('shopId', Form::prepareDropdown($stocks))->setValue(input_get('shopId')), true,
                'Торговая точка'
            )
            ->addField(
                $this->controlBuilder->buildDropdownUniform('userGroupId',
                    Form::prepareDropdownWithDef($userGroups, '', 'права доступа')
                )->setValue($currentUserGroupId), false,
                'Доступ в систему', 'персональный доступ к системе'
            );

        $table
            ->addFilter(
                $this->controlBuilder->buildInput('search_by_name')
            )
            ->addFilter(
                $this->controlBuilder->buildInput('search_by_email')
            )
            ->addFilter(
                $this->controlBuilder->buildDropdownUniform('filter_by_stockId', Form::prepareDropdown($stocks))
            );

        return $table->render();
    }

    public function formatCountCustomers(ManagerEntityInterface $managerEntity): string
    {
        $count = $this->customerRepository->count(CustomerCriteria::create()->setFilterByManagerId($managerEntity->getId()));

        return $count;
    }

    /**
     * @param ManagerEntityInterface $managerEntity
     * @return string
     * @throws \Repo\Concrete\Exceptions\Collection
     */
    public function formatAccess(ManagerEntityInterface $managerEntity): string
    {
        $users = $this->userRepository->findByCriteria(
            UserCriteria::create()->setFilterByEmail($managerEntity->getEmail())
        );

        if ($users->count() === 0) {
            return '-';
        } elseif ($users->count() > 1) {
            return Form::buildIcon('info', 'Обнаружено несколько пользователей привязанных к данному менеджеру');
        }
        $user = $users->current();

        $access = $user->getPassword() > '' ? '' : Form::buildIcon('info', 'Пароль не задан');

        return anchor('/admin/diamond/system/users?filter=1&filter_by_id=' . $user->getId(),
            sprintf(
                '%s (%s) %s',
                $user->getName(),
                $user->getUserGroup()->getName(),
                $access
            )
            , [
                'target' => '_blank'
            ]);
    }

    /**
     * @param ManagerEntityInterface|Manager $managerEntity
     * @return string
     * @throws \Propel\Runtime\Exception\PropelException
     * @throws \Repo\Concrete\Exceptions\Collection
     */
    public function formatCustomerAccess(ManagerEntityInterface $managerEntity): string
    {

        $customers = $this->customerRepository->findByCriteria(
            CustomerCriteria::create()->setFilterByEmail($managerEntity->getEmail())
                ->setFilterByGroupIds(
                    $this->customerGroups
                )
        );
        if ($customers->count() === 0) {
            return anchor('/admin/shop/customers/customers?fn=add&form[email]=' .
                $managerEntity->getEmail() . '&form[groupId]=' .
                $this->mainConf->getDefaultCustomerGroup() .
                '&form[managerId]=' . $managerEntity->getId() .
                '&form[phone]=' . $managerEntity->getPhone() .
                '&form[name]=' . $managerEntity->getName() .
                '&form[cityId]=' .$managerEntity->getShop()->getAddress()->getCityId(),
                'создать'
                , [
                    'target' => '_blank'
                ]);
        } elseif ($customers->count() > 1) {
            return anchor('/admin/shop/customers/customers?filter=1&search_by_email=' . $managerEntity->getEmail(),
                Form::buildIcon('info', 'Обнаружено несколько пользователей привязанных к данному менеджеру') .
                ' Исправить'
                , [
                    'target' => '_blank'
                ]);
        }

        /** @var Customer $customer */
        $customer = $customers->current();

        $access = $customer->getPassword() > '' ? '' : Form::buildIcon('info', 'Пароль не задан');

        return anchor('/admin/shop/customers/customers?filter=1&search_by_email=' . $customer->getEmail(),
            sprintf(
                '%s (%s) %s',
                $customer->getName(),
                $customer->getCustomerGroup()->getName(),
                $access
            )
            , [
                'target' => '_blank'
            ]);
    }

    /**
     * @param ManagerEntityInterface $managerEntity
     * @return string
     */
    public function formatComment(ManagerEntityInterface $managerEntity): string
    {
        return Text::clearText($managerEntity->getComment() ?? '', 120);
    }

    /**
     * @param ManagerEntityInterface $managerEntity
     * @return string
     */
    public function formatShop(ManagerEntityInterface $managerEntity): string
    {

        return $managerEntity->getShop()->getTitleWithType();
    }


    public function actionCreateUserAfterUpdate(array $data, \Core\Form\RepoForm $form)
    {
        try {
            if (!empty($data["userGroupId"])) {

                $user = $this->userService->creatOrUpdateUser($data["name"], $data["email"], $data["userGroupId"]);

                $form->addCustomMessage(
                    "Пользователь системы успешно создан",
                    \Core\Form\RepoForm::MESSAGE_SUCCESS
                );
            }

        } catch (\Diamond\Exceptions\UserException $ex) {

            $form->addCustomMessage(
                "Не удалось создать пользователя системы, ошибка: " . $ex->getMessage(),
                \Core\Form\RepoForm::MESSAGE_ERROR
            );
        }

        return true;
    }

    /**
     *
     * @param array $data
     * @param \Core\Form\RepoForm $form
     * @return boolean
     */
    public function actionManagerValidate(array $data, \Core\Form\RepoForm $form)
    {

        //редактирование записи, сразу выход
        if ($form->getEntity()->getId() > 0) {
            return $data;
        }

        $manager = \Shop\Models\Manager\ManagerQuery::create()
            ->findOneByEmail($data["email"]);

        if (!$manager) {
            return $data;
        }

        $form->addCustomMessage(sprintf(
            "Менеджер с указанным email `%s` уже существует, укажите другой email", $data["email"]
        ), \Core\Form\RepoForm::MESSAGE_ERROR);

        return false;
    }

    public function buildMoveCustomersForm(array $managersAr): Simpleform
    {
        $form = $this->formBuilder->buildSimpleValidationForm('move-customers');

        $ids = Form::getIdsFromRequest();

        foreach ($ids as $id) {
            unset($managersAr[(int)$id]);
        }

        $form
            ->addField(
                $this->controlBuilder->buildAutoDropdown('manager_id', $managersAr),
                'Новый менеджер для клиентов',
                ['required']
            )
            ->addField(
                $this->controlBuilder->buildHidden('ids', input_post('ids'))
            )
            ->addField(
                $this->controlBuilder->buildHidden('actiontype', input_post('actiontype'))
            )
            ->addControl(
                $this->controlBuilder->buildSubmitButton('submit_change_manager', 'Сменить менеджера')
            )
            ->addControl($this->controlBuilder->buildCancel('cancel',
                'Отмена'
            ));

        return $form;
    }

}               