<?php

namespace Shop\Presentation\Modules\AdminCategories;

use ActiveTable\ColumnTable;
use ActiveTable\DataTableEngine;
use Core\Concrete\RequestAwareTrait;
use Core\Contracts\RequestAwareInterface;
use Core\Form\Control\Menu;
use Core\Form\Control\MenuItemDelete;
use Core\Form\Control\MenuItemEdit;
use Core\Form\ControlBuilder;
use Core\Helpers\Text;
use Core\ModuleController;
use Core\Template\Template;
use Diamond\Helpers\Form;
use DiamondTable\TableFactory;
use Shop\Domain\Catalog\Contracts\CatalogEntityInterface;
use Shop\Domain\ProductCategory\Contracts\ProductCategoryEntityInterface;
use Shop\Infrastructure\Models\Category\Category;
use Shop\Infrastructure\Models\Category\CategoryQuery;
use Shop\Infrastructure\Repositories\Catalog\CatalogCriteria;
use Shop\Infrastructure\Repositories\Catalog\CatalogRepository;
use Shop\Infrastructure\Repositories\Product\ProductCriteria;
use Shop\Infrastructure\Repositories\Product\ProductRepository;
use Shop\Infrastructure\Repositories\ProductCategory\ProductCategoryCriteria;
use Shop\Infrastructure\Repositories\ProductCategory\ProductCategoryRepository;
use Shop\Presentation\Modules\Traits\FormatterTrait;

/**
 * Description of AdminCategories
 *
 * @author Dmitriy
 */
class AdminCategories extends ModuleController implements RequestAwareInterface
{

    public int|null $parentId = null;
    use FormatterTrait;
    use RequestAwareTrait;

    public function __construct(protected ProductCategoryRepository $productCategoryRepository,
                                protected ProductRepository         $productRepository,
                                protected CatalogRepository         $catalogRepository,
                                protected TableFactory              $tableFactory,
                                protected Template                  $template,
                                protected ControlBuilder            $controlBuilder)
    {

    }


    public function process(): string
    {

        $this->template->addStyleLink('/_diamond/diamond-cms/assets/nifty/plugins/fooTable/css/footable.core.css');
        $this->template->addScript($this->render('javascript'));

        $list = $this->productCategoryRepository->findByCriteria(
            ProductCategoryCriteria::create()
        );
        $listCatalog = $this->catalogRepository->findByCriteria(
            CatalogCriteria::create()
        );

        $catalogAr = Form::prepareDropdown($listCatalog);
        $listAr = Form::prepareDropdownWithDef($list, 'NULL', 'без родительского', 'getDropdownListWithParent');

        if (input_get('id') > 0) {
            unset($listAr[input_get('id')]);
        }

        $criteria = ProductCategoryCriteria::create();

        if (!input_get('id') && !input_post('actiontype')) {
            if ($this->parentId) {
                $criteria->setFilterByParentIds([$this->parentId]);
            } else {
                $criteria->setFilterByParentIdIsNull(true);
            }
        }
        $parentCategory = null;

        if ($this->request->query->get('parent_id')) {
            $parentCategory = $this->productCategoryRepository->findById($this->request->query->get('parent_id'));
        }


        $catalogId = $parentCategory?->getCatalogId() ?? null;

        $table = $this->tableFactory->buildAdminTable($this->productCategoryRepository,
            $criteria
        //->setAsTreeView(true)
        );

        $table
            ->removeControlAccess(DataTableEngine::CONTROL_ROWS_SELECT)
            ->setClass('nifty-table dataTable  table table-striped footable breakpoint toggle-circle');


        $this->prepareColumns($table);
//            ->addRowActionCommand(
//                'change-catalog',
//                new ChangeCatalogCommand($table, $this->buildMoveBrandForm($catalogAr)),
//                'Сменить каталог'
//            );

        $table
            ->addField(
                $this->controlBuilder
                    ->buildInput('title'), true
            )
            ->addField(
                $this->controlBuilder
                    ->buildInput('alias'), true, 'Псевдоним на латинице', 'для использования в ЧПУ'
            );


        if ($catalogId) {
            $table
                ->addField(
                    $this->controlBuilder
                        ->buildHidden('catalogId', $catalogId)
                );
        } else {
            $table
                ->addField(
                    $this->controlBuilder
                        ->buildDropdownUniform('catalogId', $catalogAr)
                        ->setValue($this->request->query->get('catalog_id') ?? 'NULL')
                    , true, 'Каталог'
                );
        }

        $table->addField(
            $this->controlBuilder
                ->buildDropdownUniform('parentId', $listAr)
                ->setValue($this->request->query->get('parent_id') ?? 'NULL')
            , true, 'Родительский раздел'
        )
            ->addField(
                $this->controlBuilder
                    ->buildTextEditor('desc')
                    ->setHeight(200)
                    ->setCompact(true)
            );

        $table
            ->addFilter(
                $this->controlBuilder->buildInput('search_by_title')
            );


//        $this->buildForm($table, $catalogAr);

        return $table->render();
    }

    /**
     * @param ProductCategoryEntityInterface $categoryEntity
     * @return string
     * @throws \Propel\Runtime\Exception\PropelException
     */
    public function formatParent(ProductCategoryEntityInterface $categoryEntity): string
    {
        if (!$categoryEntity->getParentCategory()) {
            return '';
        }
        return $categoryEntity->getParentCategory()->getTitle();
    }

    /**
     * @param ProductCategoryEntityInterface $categoryEntity
     * @return string
     */
    public function formatDesc(ProductCategoryEntityInterface $categoryEntity): string
    {
        if (!$text = $categoryEntity->getDesc()) {
            return '';
        }
        $txt = Text::clearText($text, 30);
        return $txt !== '' ? $txt . '...' : '';
    }


    protected function prepareColumns(DataTableEngine $table): void
    {
        $table
            ->addColumn(
                (new ColumnTable('id', '№'))->setWidth(40)
            )
            ->addColumn(
                (new ColumnTable('title', 'Наименование'))
                    ->setFormat($this, 'formatTitle')
            )
//            ->addColumn(
//                (new ColumnTable('parent', 'Родитель'))
//                    ->setFormat($this, 'formatParent')
//            )
            ->addColumn(
                (new ColumnTable('alias', 'Псевдоним'))
            )
            ->addColumn(
                (new ColumnTable('products', 'Товаров'))
                    ->setFormat($this, 'formatProducts')
                    ->setWidth(10, true)
            )
            ->addColumn(
                (new ColumnTable('image', 'Изображение'))
            )
            ->addColumn(
                (new ColumnTable('desc', 'Описание'))
                    ->setFormat($this, 'formatDesc')
            )
            ->addColumn(
                (new ColumnTable('catalog', 'Каталог'))
                    ->setFormat($this, 'formatCatalog')
            )
            ->addColumn(
                (new ColumnTable('actions', ''))
                    ->setFormat($this, 'formatActions')
                    ->setWidth(140)
            );
    }


    /**
     * @param ProductCategoryEntityInterface|Category $categoryEntity
     * @return string
     */
    public function formatProducts(ProductCategoryEntityInterface $categoryEntity): string
    {
        $count = $this->productRepository->count(
            ProductCriteria::create()->setFilterByCategoryId($categoryEntity->getId())
        );

        $childs = $this->productCategoryRepository->findByCriteria(ProductCategoryCriteria::create()->setFilterByParentIds(
            [$categoryEntity->getId()]
        ));

        foreach ($childs as $child) {
            $countChild = $this->productRepository->count(
                ProductCriteria::create()->setFilterByCategoryId($child->getId())
            );
            $count += $countChild;
        }

        return (string)$count;
    }

    /**
     * @param ProductCategoryEntityInterface $categoryEntity
     * @return string
     */
    public function formatActions(ProductCategoryEntityInterface $categoryEntity, $items = []): string
    {
        $id = $categoryEntity->getId();

        return (new Menu(
            array_merge($items, [
                anchor(
                    admin_path(
                        '/shop/catalog/categories?fn=add&parent_id=' . $id
                    ),
                    Form::buildIconText('pencil_white', 'Добавить подраздел')),
                new MenuItemEdit($id, admin_path(
                    '/shop/catalog/categories?fn=edit&id=' . $id
                )),
                new MenuItemDelete($id)
            ])))->render();
    }

    /**
     * @param ProductCategoryEntityInterface|Category $categoryEntity
     * @return string
     */
    public function formatTitle(ProductCategoryEntityInterface $categoryEntity): string
    {

        $title = $categoryEntity->getTitle();

        $step = 16;

        $margin = $categoryEntity->getParentId() ? $step : 0;

        $class = '';

        if ($categoryEntity->getParentCategory()) {
            $class .= 'parent-' . $categoryEntity->getParentCategory()->getId();

            if ($categoryEntity->getParentCategory()->getParentCategory()) {
                $class .= ' parent-' . $categoryEntity->getParentCategory()->getParentId();
                $margin += $step;
            }

        }

        if ($categoryEntity->getVirtualColumn('child_exist') > 0) {
            $toggle = '<span class="footable-toggle ' . $class . '" style="position: absolute;margin-left:' . $margin . 'px" data-id="' . $categoryEntity->getId() . '"></span>';
        } else {
            $toggle = '<span class="' . $class . '" style="width: ' . ($step + $margin) . 'px;display: inline-block;position: absolute;"></span>';
        }

        $title = (nbs($categoryEntity->getParentsLevel() * 7) .
            ($categoryEntity->getCountChildrens() > 0 ? '<i class="fa fa-folder"></i> ' : '') .
            $title);

        return
            $toggle . $this->formatNamePart($title, $step, $margin);
    }

    private function formatNamePart(string $name, int $step, int $margin): string
    {
        $style = 'position: relative; margin-left: ' . ($step + $margin) . 'px';
        return '<div style="' . $style . '">' . $name . '</div>';
    }

    /**
     * @param ProductCategoryEntityInterface $product
     * @return string
     */
    public function formatCatalog(ProductCategoryEntityInterface $category): string
    {
        return is_object($category->getCatalog()) ? $category->getCatalog()->getName() : '';
    }

}