<?php

namespace Shop\Modules\AdminProducts;

use ActiveTable\ColumnTable;
use ActiveTable\DataTableEngine;
use Core\Form\ControlBuilder;
use Core\Form\FormBuilder;
use Core\Helpers\Text;
use Core\ModuleController;
use Shop\Application\Catalog\CatalogService;
use Shop\Config\Main;
use Diamond\Helpers\Form;
use Diamond\Helpers\Formatter;
use DiamondTable\TableFactory;
use Shop\Domain\Product\Contracts\ProductEntityInterface;
use Shop\Models\Product\Product;
use Shop\Modules\AdminClients\MergerOrdersCommand;
use Shop\Modules\AdminProducts\MergerProductsCommand;
use Shop\Repositories\Brand\BrandCriteria;
use Shop\Repositories\Brand\BrandRepository;
use Shop\Repositories\Product\ProductCriteria;
use Shop\Repositories\Product\ProductRepository;
use Shop\Repositories\ProductCategory\ProductCategoryCriteria;
use Shop\Repositories\ProductCategory\ProductCategoryRepository;
use Shop\Repositories\ProductGroup\ProductGroupCriteria;
use Shop\Repositories\ProductGroup\ProductGroupRepository;
use Shop\UseCases\Imaging\Imaging;
use spaceonfire\CommandBus\CommandBus;

/**
 * Description of AdminProducts
 *
 * @author Dmitriy
 */
class AdminProducts extends ModuleController
{
    use FormTrait;

    protected $tableFactory;
    protected $productCategoryRepository;
    protected $brandRepository;
    protected $mainConfig;
    protected $catalogService;
    protected $productGroupRepository;


    protected $commandBus;

    /**
     * AdminProducts constructor.
     * @param ProductRepository $productRepository
     * @param ControlBuilder $controlBuilder
     * @param TableFactory $tableFactory
     * @param ProductCategoryRepository $productCategoryRepository
     * @param BrandRepository $brandRepository
     * @param Main $mainConfig
     * @param CatalogService $catalogService
     * @param FormBuilder $formBuilder
     * @param ProductGroupRepository $productGroupRepository
     * @param CommandBus $commandBus
     */
    public function __construct(ProductRepository $productRepository,
                                ControlBuilder $controlBuilder,
                                TableFactory $tableFactory,
                                ProductCategoryRepository $productCategoryRepository,
                                BrandRepository $brandRepository,
                                Main $mainConfig,
                                CatalogService $catalogService,
                                FormBuilder $formBuilder,
                                ProductGroupRepository $productGroupRepository,
                                CommandBus $commandBus)
    {
        $this->productRepository = $productRepository;
        $this->tableFactory = $tableFactory;
        $this->controlBuilder = $controlBuilder;
        $this->productCategoryRepository = $productCategoryRepository;
        $this->brandRepository = $brandRepository;
        $this->mainConfig = $mainConfig;
        $this->catalogService = $catalogService;
        $this->formBuilder = $formBuilder;
        $this->productGroupRepository = $productGroupRepository;

        $this->commandBus = $commandBus;
    }


    /**
     * @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
    {

        $table = $this->tableFactory->buildAdminTable($this->productRepository, ProductCriteria::create());

        $categories = $this->productCategoryRepository->findByCriteria(
            ProductCategoryCriteria::create()->setSortByTitle('ASC')
        );

        $categoriesAr = Form::prepareDropdown($categories, 'Раздел каталога', 'getDropdownListWithParent');

        $brands = $this->brandRepository->findByCriteria(
            BrandCriteria::create()
        );

        $brandsAr = Form::prepareDropdown($brands);

        //$groups
        $groups = $this->productGroupRepository->findByCriteria(
            ProductGroupCriteria::create()
        );
        $groupsAr = $groups->getDropDownList();

        $productGroupsIds = [];
        /**
         * @var Product $product
         */
        if (input_get('id')) {
            $product = $this->productRepository->findById(input_get('id'));

            if($product && $product->getProductGroups()){
                $productGroupsIds = array_keys($product->getProductGroups()->toKeyIndex());
            }
        }


        $table
            ->addRowActionCommand(
                'change-category',
                new ChangeCategoryCommand($table, $this->buildMoveCategoryForm($categoriesAr)),
                'Сменить радел каталога'
            )
            ->addRowActionCommand(
                'change-brand',
                new ChangeBrandCommand($table, $this->buildMoveBrandForm($brandsAr)),
                'Сменить производителя'
            )
            ->addRowActionCommand(
                'merge-products',
                new MergerProductsCommand($table, $this->buildMergerProductsForm(), $this->commandBus),
                'Объеденить товары'
            );


        $table
            ->setDefaultSortColumn('id', 'desc')
            ->addColumn(
                (new ColumnTable('id', '№'))
                    ->setWidth(60)
            )
            ->addColumn(
                (new ColumnTable('article', 'Артикул'))
                    ->setFormat($this, 'formatArticle')
            )
            ->addColumn(
                (new ColumnTable('title', 'Наименование'))

            )
            ->addColumn(
                (new ColumnTable('weight', 'Вес'))

            )
            ->addColumn(
                (new ColumnTable('price', 'Цена'))

            )
            ->addColumn(
                (new ColumnTable('pricePositions', 'Позиций'))
                    ->setFormat($this, 'formatPosCount')

            )
            ->addColumn(
                (new ColumnTable('categoryId', 'Раздел'))
                    ->setFormat($this, 'formatCategory')

            )
            ->addColumn(
                (new ColumnTable('brand', 'Производитель'))
                    ->setFormat($this, 'formatBrand')

            )
            ->addColumn(
                (new ColumnTable('groups', 'Группы товара'))
                    ->setFormat($this, 'formatGroups')

            )
            ->addColumn(
                (new ColumnTable('imageexist', 'Изобр.-е'))
                    ->setFormat($this, 'formatImage')

            )
            ->addColumn(
                (new ColumnTable('active', 'Опубликован'))
                    ->setFormat($this, 'formatActive')

            )
            ->addColumn(
                (new ColumnTable('special', 'Спец. предложение'))
                    ->setFormat($this, 'formatSpecial')

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


        $table
            ->addFilter(
                $this->controlBuilder->buildInput('filter_by_id')
            )
            ->addFilter(
                $this->controlBuilder->buildInput('search_by_article')
            )
            ->addFilter(
                $this->controlBuilder->buildInput('search_by_title')
            )
            ->addFilter(
                $this->controlBuilder->buildInput('search_by_brand')
            )
            ->addFilter(
                $this->controlBuilder->buildDropdownUniform('filter_by_categoryId',
                    $categoriesAr
                )
            )
            ->addFilter(
                $this->controlBuilder->buildDropdownYNUniform('filter_by_active', [
                    null => 'любой'
                ])
            )
            ->addFilter(
                $this->controlBuilder->buildDropdownYNUniform('filter_by_special', [
                    null => 'любой'
                ])
            )
            ->addFilter(
                $this->controlBuilder->buildDropdownYNUniform('filter_by_imageexist', [
                    null => 'Любой',
                    'Y' => 'Есть'
                ])
            );

        $this->buildForm($table, $categoriesAr, $brandsAr, $groupsAr, $productGroupsIds);

        return $table->render();
    }

    /**
     * @param DataTableEngine $table
     * @param array $categoriesAr
     * @param array $brandsAr
     * @param array $groupsAr
     * @param array $productGroupsIds
     * @throws \ReflectionException
     * @throws \Twig\Error\LoaderError
     * @throws \Twig\Error\RuntimeError
     * @throws \Twig\Error\SyntaxError
     */
    protected function buildForm(DataTableEngine $table, array $categoriesAr, array $brandsAr, array $groupsAr, array $productGroupsIds): void
    {

        $imgUpload = $this->controlBuilder
            ->buildImgUpload('img', $this->catalogService->getProductsImageDir(), true)
            ->setPreviewImage(true);

        $brandName = $categoryName = '';
        $brandId = $categoryId = null;

        if (input_get('id')) {
            $product = $this->productRepository->findById(input_get('id'));
            if ($product) {
                $brandName = $product->getBrand()->getName();
                $categoryName = $product->getCategory()->getTitle();
            }
        }
        else{
            $brand = $this->brandRepository->findById($this->mainConfig->getDefaultBrandId());
            if($brand){
                $brandName = $brand->getName();
                $brandId = $brand->getId();
            }
            $category = $this->productCategoryRepository->findById($this->mainConfig->getDefaultCategoryId());
            if($category){
                $categoryName = $category->getTitle();
                $categoryId = $category->getId();
            }
        }


        $table
            ->addField(
                $this->controlBuilder->buildInput('title'), true
            )
            ->addField(
                $this->controlBuilder->buildInput('article')
            )
            ->addField(
                $this->controlBuilder->buildTextArea('shortDesc'), false, 'Краткое описание'
            )
            ->addField(
                $this->controlBuilder->buildWindowSelect(
                    'categoryId',
                    '/admin/shop/catalog/categories-lite?filter=1',
                    $categoryName
                )->setValue($categoryId), true
               // $this->controlBuilder->buildAutoDropdown('categoryId', $categoriesAr), true
            )
            ->addField(
                $this->controlBuilder->buildWindowSelect(
                    'brandId',
                    '/admin/shop/catalog/brands-lite?filter=1',
                    $brandName
                )->setValue($brandId), true,'Производитель'
            )
            ->addField(
                $this->controlBuilder->buildInputTiny('price')
            )
            ->addField(
                $this->controlBuilder->buildSpinner('weight',1000000)->setValue(0)->setWidth(50)
            )
            ->addField(
                $this->controlBuilder->buildDropdownYNUniform('active')->setValue('Y'), true
            )
            ->addField(
                $this->controlBuilder->buildDropdownYNUniform('special')->setValue('N'), true, 'Специальное предложение'
            )
            ->addField(
                $this->controlBuilder->buildSpinner('minQuality')
                    ->setValue(1), false, 'Минимальное кол-во товара в упаковке'

            )
            ->addField(
                $this->controlBuilder->buildTextEditor('desc')
                    ->setHeight(200)
                    ->setCompact(true), false, 'Описание'
            )
            ->addField(
                $imgUpload, false, 'Изображение товара'
            )
            ->addField(
                $this->controlBuilder->buildAutoDropdownMulti('groups', $groupsAr)->setValue($productGroupsIds), false, 'Группы товара'
            );

        if ($file = $imgUpload->UploadImage()) {
            Form::addTableNotice(
                Form::buildSuccessMessage(sprintf('Изображение %s успешно сохранено', $file))
            );
        } elseif ($imgUpload->deleteImage()) {
            Form::addTableNotice(
                Form::buildErrorMessage('Изображение успешно удалено')
            );
        }
    }

    /**
     * @param ProductEntityInterface|Product $product
     * @return string
     */
    public function formatGroups(ProductEntityInterface $product): string
    {

        return implode(', ', $product->getGroupListArray());
    }

    /**
     * @param ProductEntityInterface $product
     * @return string
     */
    public function formatPosCount(ProductEntityInterface $product): string
    {
        return (string)$product->getPositionsCount();
    }

    /**
     * @param ProductEntityInterface $product
     * @return string
     */
    public function formatImage(ProductEntityInterface $product): string
    {
        return $product->getImg() > '' ? Form::buildIcon('image') : '';
    }

    /**
     * @param ProductEntityInterface $product
     * @return string
     */
    public function formatActive(ProductEntityInterface $product): string
    {
        return Formatter::formatYN($product->getActive(), [
            'N' => 'color-alert', 'Y' => 'color-success']);
    }

    /**
     * @param ProductEntityInterface $product
     * @return string
     */
    public function formatSpecial(ProductEntityInterface $product): string
    {
        return Formatter::formatYN($product->getSpecial(),
            ['Y' => 'color-success']);
    }

    /**
     * @param ProductEntityInterface $product
     * @return string
     */
    public function formatBrand(ProductEntityInterface $product): string
    {
        return $product->getBrand()->getName();
    }

    /**
     * @param ProductEntityInterface $product
     * @return string
     */
    public function formatCategory(ProductEntityInterface $product): string
    {
        return $product->getCategory()->getNameWithParentName();
    }

    /**
     * @param ProductEntityInterface $product
     * @return string
     */
    public function formatArticle(ProductEntityInterface $product): string
    {
        if(!$product->getArticle()){
            return '';
        }
        $text = Text::clearText($product->getArticle(),20);
        return $text . ($text !== $product->getArticle() ?  '...':'');
    }

}