<?php

/**
 * Created by PhpStorm.
 * User: wpj
 * Date: 10.11.17
 * Time: 13:19.
 */

namespace KupShop\IndexedFilterBundle\Util;

use KupShop\CatalogBundle\Section\SectionTree;
use KupShop\I18nBundle\Translations\ParametersListTranslation;
use KupShop\I18nBundle\Translations\ProducersTranslation;
use KupShop\I18nBundle\Translations\VariationsValuesTranslation;
use Query\Operator;
use Query\Translation;

class FilterUrlGenerator
{
    /** @var \FilterParams */
    protected $filterParams;
    /** @var string */
    protected $categoryUrl;
    protected $filter = [];
    protected $indexedParamsCount = 1;
    private $ignoreProducer = false;
    private $section = [];
    private $producers = [];
    private $parameters = [];
    private $variations = [];
    private $variationsSizeConvertion = [];
    private $sectionId;

    /**
     * @var SectionTree
     */
    private $sectionTree;

    /**
     * @required
     */
    public function setSectionTree(SectionTree $sectionTree): void
    {
        $this->sectionTree = $sectionTree;
    }

    protected function prepareFilterParams()
    {
        $params = $this->filterParams->getParams();

        $section = null;
        $section_id = 0;
        if (!is_null($this->sectionId)) {
            $section_id = $this->sectionId;
        } elseif ($params['sectionIds']) {
            $section_id = $params['sectionIds'][0];
        }
        $qb = sqlQueryBuilder()->select('s.id, s.name, s.filter_url, s.producers_indexing, s.producers_to_title')
            ->from('sections', 's')
            ->where('s.id = '.$section_id);
        $section = $qb->execute()->fetch();
        if (!$section) {
            $section = [
                'id' => 0,
                'producers_to_title' => true,
                'producers_indexing' => false,
            ];
        }
        $this->section = $section;

        if (!$this->ignoreProducer) {
            $producers = $params['producers'];
            if ($producers) {
                $qb = sqlQueryBuilder()->select('pr.id')
                    ->from('producers', 'pr')
                    ->where('pr.active="Y"')
                    ->andWhere(Operator::inIntArray($producers, 'pr.id'))
                    ->andWhere(Translation::coalesceTranslatedFields(ProducersTranslation::class, ['name', 'filter_url']))
                    ->orderBy('pr.position, pr.name');
                $this->producers = sqlFetchAll($qb);
            }
        }
        if ($this->producers) {
            $this->filter[] = ['type' => 'producers', 'indexed' => $this->section['producers_indexing'], 'producers' => $this->producers];
        }

        if ($params['campaigns']) {
            $this->filter[] = ['type' => 'campaigns', 'indexed' => 'N', 'campaigns' => $params['campaigns']];
        }

        if ($params['inStore']) {
            $this->filter[] = ['type' => 'inStore', 'indexed' => 'N', 'inStore' => $params['inStore']];
        }

        if ($params['stores']) {
            $this->filter[] = ['type' => 'stores', 'indexed' => 'N', 'stores' => $params['stores']];
        }

        if ($params['priceRange']) {
            $this->filter[] = ['type' => 'price', 'indexed' => 'N', 'priceRange' => $params['priceRange']];
        }

        $section_id = $this->section['id'];
        $parameters = $params['parameters'];
        $qb = sqlQueryBuilder()->select('ps.id_parameter AS id, ps.indexing, ps.to_title')
            ->from('parameters_sections', 'ps')
            ->where('ps.id_section = '.$section_id);
        $section_parameters = sqlFetchAll($qb);
        $parameter_ids = array_column($section_parameters, 'id');
        $section_parameters = array_combine($parameter_ids, $section_parameters);
        $this->parameters = $section_parameters;
        if ($parameters) {
            $parameters_to_url_ids = [];
            $list_parameters = array_filter($parameters, function ($p) {return $p['type'] == 'list'; });
            if (!empty($list_parameters)) {
                $qb = sqlQueryBuilder()->select('ps.indexing, ps.to_title, pl.id, pl.id_parameter')
                    ->from('parameters_list', 'pl')
                    ->leftJoin('pl', 'parameters_sections', 'ps', 'pl.id_parameter = ps.id_parameter AND ps.id_section = '.$section_id)
                    ->where('ps.to_title = "Y"')
                    ->andWhere(Translation::coalesceTranslatedFields(ParametersListTranslation::class, ['value', 'filter_url']));
                $keys = array_keys($list_parameters);
                $or = null;
                foreach ($keys as $parameter_id) {
                    $list_parameter_i = $list_parameters[$parameter_id];
                    $or2 = Operator::andX('ps.id_parameter = '.$parameter_id, Operator::inIntArray($list_parameter_i['values'], 'pl.id'));
                    $or = Operator::orX($or, $or2);
                }
                $qb->andWhere($or);
                $qb->orderBy('pl.id_parameter, pl.id');
                $parameters_to_url = sqlFetchAll($qb);
                if (!empty($parameters_to_url)) {
                    $parameters_to_url_ids = array_unique(array_column($parameters_to_url, 'id_parameter'));
                    foreach ($parameters_to_url_ids as $key) {
                        if (array_key_exists($key, $section_parameters)) {
                            $parameter = $section_parameters[$key];
                            $parameter_values = array_filter($parameters_to_url, function ($p) use ($key) { return $p['id_parameter'] == $key; });
                            $parameter_values = array_combine(array_column($parameter_values, 'id'), $parameter_values);
                            $parameter['values'] = $parameter_values;
                            $parameter['type'] = 'list';
                            $this->parameters[$key] = $parameter;
                            $this->filter[] = ['type' => 'parameter', 'indexed' => $this->parameters[$key]['indexing'], 'parameter' => $this->parameters[$key]];
                        }
                    }
                }
            }
            $parameters_to_query_string = array_diff_key($parameters, array_flip($parameters_to_url_ids));
            foreach ($parameters_to_query_string as $key => $parameter) {
                $parameter_values = array_map(function ($v) { return ['id' => $v]; }, $parameter['values']);
                $parameter_values = array_combine(array_column($parameter_values, 'id'), $parameter_values);
                if (!array_key_exists($key, $this->parameters)) {
                    $this->parameters[$key] = ['id' => $key, 'to_title' => 'N', 'indexing' => 'N'];
                }
                $this->parameters[$key]['values'] = $parameter_values;
                $this->parameters[$key]['type'] = $parameter['type'];
                $this->filter[] = ['type' => 'parameter', 'indexed' => $this->parameters[$key]['indexing'], 'parameter' => $this->parameters[$key]];
            }
        }

        $variations = $params['variations'];
        $qb = sqlQueryBuilder()->select('pvs.id_label AS id, pvs.indexing, pvs.to_title')
            ->from('products_variations_sections', 'pvs')
            ->where('pvs.id_section = '.$section_id);
        $section_variations = sqlFetchAll($qb);
        $variation_ids = array_column($section_variations, 'id');
        $section_variations = array_combine($variation_ids, $section_variations);
        $this->variations = $section_variations;
        if ($variations) {
            $qb = sqlQueryBuilder()->select('pvs.indexing, pvs.to_title, pvcv.id, pvcv.id_label')
                ->from('products_variations_choices_values', 'pvcv')
                ->leftJoin('pvcv', 'products_variations_sections', 'pvs', 'pvcv.id_label = pvs.id_label AND pvs.id_section = '.$section_id)
                ->where('pvs.to_title = "Y"')
                ->andWhere(Translation::coalesceTranslatedFields(VariationsValuesTranslation::class, ['value', 'filter_url']));
            $keys = array_keys($variations);
            $or = null;
            foreach ($keys as $label_id) {
                $variation_i = $variations[$label_id];
                $or2 = Operator::andX('pvcv.id_label = '.$label_id, Operator::inIntArray($variation_i, 'pvcv.id'));
                $or = Operator::orX($or, $or2);
            }
            $qb->andWhere($or);
            $variations_to_url = sqlFetchAll($qb);
            $variations_to_url_ids = [];
            if (!empty($variations_to_url)) {
                $variations_to_url_ids = array_unique(array_column($variations_to_url, 'id_label'));
                foreach ($variations_to_url_ids as $key) {
                    if (array_key_exists($key, $section_variations)) {
                        $variation = $section_variations[$key];
                        $variation_values = array_filter($variations_to_url, function ($v) use ($key) { return $v['id_label'] == $key; });
                        $variation_values = array_combine(array_column($variation_values, 'id'), $variation_values);
                        $variation['values'] = $variation_values;
                        $this->variations[$key] = $variation;
                        $this->filter[] = ['type' => 'variation', 'indexed' => $this->variations[$key]['indexing'], 'variation' => $this->variations[$key]];
                    }
                }
            }
            $variations_to_query_string = array_diff_key($variations, array_flip($variations_to_url_ids));
            foreach ($variations_to_query_string as $key => $variation) {
                $variation_values = array_map(function ($v) { return ['id' => $v]; }, $variation);
                $variation_values = array_combine(array_column($variation_values, 'id'), $variation_values);
                if (!array_key_exists($key, $this->variations)) {
                    $this->variations[$key] = ['id' => $key, 'to_title' => 'N', 'indexing' => 'N'];
                }
                $this->variations[$key]['values'] = $variation_values;
                $this->filter[] = ['type' => 'variation', 'indexed' => $this->variations[$key]['indexing'], 'variation' => $this->variations[$key]];
            }
        }

        if (findModule(\Modules::CONVERTORS)) {
            // fetch všech hodnot z PL pro převodník stylem [id => pl.id, name => pl.name => pl.filter_url]
            $variationsSizeConvertion = $params['variationsSizeConvertion'];
            $qb = sqlQueryBuilder()->select('pvs.convertor AS id, pvs.indexing, pvs.to_title, pvs.convertor')
                ->from('products_variations_sections', 'pvs')
                ->where(Operator::equals(['pvs.id_section' => $section_id]))
                ->andWhere('pvs.convertor IS NOT NULL');

            $section_variations_convertors = [];
            foreach (sqlFetchAll($qb) as $item) {
                $section_variations_convertors[$item['convertor']] = $item;
            }

            $convertors_ids = array_column($section_variations_convertors, 'convertor');
            $selectedIds = [];
            foreach ($variationsSizeConvertion as $item) {
                foreach ($item['value'] as $value) {
                    $selectedIds[$value] = $value;
                }
            }

            if (!empty($selectedIds)) {
                $qb = sqlQueryBuilder()->select('pl.id, pl.value, pl.filter_url, ct.id_convertor')
                    ->from('convertors_table', 'ct')
                    ->innerJoin('ct', 'convertors_table_values', 'ctv', 'ct.id=ctv.id_table')
                    ->innerJoin('ctv', 'parameters_list', 'pl', 'ctv.id_parameter_value=pl.id')
                    ->where(Operator::inIntArray($convertors_ids, 'ct.id_convertor'))
                    ->andWhere(Operator::inIntArray($selectedIds, 'pl.id'))
                    ->groupBy('pl.id');

                foreach ($qb->execute() as $item) {
                    $section_variations_convertors[$item['id_convertor']]['values'][$item['id']] = $item;
                }
                $this->variationsSizeConvertion = $section_variations_convertors;

                foreach ($this->variationsSizeConvertion as $item) {
                    $this->filter[] = ['type' => 'variationsSizeConvertion', 'indexed' => $item['indexing'], 'convertor' => $item];
                }
            }
        }

        if (findModule(\Modules::LABELS) && $params['labels']) {
            $this->filter[] = ['type' => 'labels', 'indexed' => 'N', 'label_ids' => $params['labels']];
        }

        if ($params['search']) {
            $this->filter[] = ['type' => 'search', 'value' => $params['search']];
        }
    }

    public function getIndexedFilter(): array
    {
        $filter = [];
        $i = 0;
        foreach ($this->filter as $f) {
            if (($f['indexed'] ?? 'N') == 'N') {
                continue;
            }
            if ($f['type'] == 'producers') {
                $producers = [];
                $producers[] = $f['producers'][0];
                $filter[$i] = ['type' => 'producers', 'indexed' => 'Y', 'producers' => $producers];
                $i++;
            }
            if ($f['type'] == 'parameter') {
                $parameter = $f['parameter'];
                $parameter_value = current($parameter['values']);
                $parameter['values'] = [];
                $parameter['values'][$parameter_value['id']] = $parameter_value;
                $filter[$i] = ['type' => 'parameter', 'indexed' => 'Y', 'parameter' => $parameter];
                $i++;
            }
            if ($f['type'] == 'variation') {
                $variation = $f['variation'];
                $variation_value = current($variation['values']);
                $variation['values'] = [];
                $variation['values'][$variation_value['id']] = $variation_value;
                $filter[$i] = ['type' => 'variation', 'indexed' => 'Y', 'variation' => $variation];
                $i++;
            }
            if ($f['type'] == 'variationsSizeConvertion') {
                $convertor = $f['convertor'];
                $convertor_value = current($convertor['values']);
                $convertor['values'] = [];
                $convertor['values'][$convertor_value['id']] = $convertor_value;
                $filter[$i] = ['type' => 'variationsSizeConvertion', 'indexed' => 'Y', 'convertor' => $convertor];
                $i++;
            }
            if ($i >= $this->indexedParamsCount) {
                break;
            }
        }

        return $filter;
    }

    public function generateUrl(): array
    {
        $url = '';
        if ($this->section) {
            $url = $this->createUrl();
        }

        return $url;
    }

    public function generateIndexedUrl(): array
    {
        $url = '';
        if ($this->section) {
            $filter = $this->getIndexedFilter();
            $url = $this->createUrl($filter);
        }

        return $url;
    }

    protected function createUrl($filter = null): array
    {
        [$url, $qs, $indexed] = $this->createUrlParts($filter);

        if (findModule(\Modules::PRODUCTS_SECTIONS, 'custom_url')
            && !empty($url) && $url !== '/'
            && !empty($this->categoryUrl)
        ) {
            $url = '/f'.$url;
        }

        $qs = rtrim($qs, '?&');

        return [
            'url' => $this->categoryUrl.$url.$qs,
            'indexed' => $indexed,
        ];
    }

    public function getProducerUrl($id_producer, $filter_url = '')
    {
        $producers[] = ['id' => $id_producer, 'filter_url' => $filter_url];

        $filter = [];
        $i = 0;
        if ($this->section['producers_indexing'] == 'Y') {
            $filter[0] = ['type' => 'producers', 'producers' => $producers];
            $i++;
        }
        if ($i < $this->indexedParamsCount) {
            $indexed_filter = $this->getIndexedFilter();
            foreach ($indexed_filter as $f) {
                if ($f['type'] == 'producers') {
                    continue;
                }
                $filter[$i] = $f;
                $i++;
                if ($i >= $this->indexedParamsCount) {
                    break;
                }
            }
        }

        return $this->createUrl($filter);
    }

    public function getParameterUrl($id_parameter, $value_id, $filter_url = '')
    {
        $parameters = $this->parameters;
        if (array_key_exists($id_parameter, $parameters)) {
            $parameter = $parameters[$id_parameter];
            $parameter_values = [];
            if (!empty($parameter['values'])) {
                $parameter_values = $parameter['values'];
            }
            if (array_key_exists($value_id, $parameter_values)) {
                unset($parameter_values[$value_id]);
            } else {
                $parameter_value = ['id' => $value_id, 'id_parameter' => $id_parameter, 'filter_url' => $filter_url];
                $parameter_values[$value_id] = $parameter_value;
            }
            $parameter['values'] = $parameter_values;
            $parameters[$id_parameter] = $parameter;
        } else {
            $parameter = ['id' => $id_parameter, 'to_title' => 'N', 'indexing' => 'N'];
            $parameter_value = ['id' => $value_id, 'id_parameter' => $id_parameter, 'filter_url' => $filter_url];
            $parameter['values'][$value_id] = $parameter_value;
            $parameters[$id_parameter] = $parameter;
        }

        $filter = [];
        $i = 0;
        if ($parameter['indexing'] == 'Y') {
            $parameter['values'] = [];
            $parameter_value = ['id' => $value_id, 'id_parameter' => $id_parameter, 'filter_url' => $filter_url];
            $parameter['values'][$value_id] = $parameter_value;
            $filter[0] = ['type' => 'parameter', 'indexed' => 'Y', 'parameter' => $parameter];
            $i++;
        }
        if ($i < $this->indexedParamsCount) {
            $indexed_filter = $this->getIndexedFilter();
            foreach ($indexed_filter as $f) {
                if (($f['type'] == 'parameter') && ($f['parameter']['id'] == $id_parameter)) {
                    continue;
                }
                $filter[$i] = $f;
                $i++;
                if ($i >= $this->indexedParamsCount) {
                    break;
                }
            }
        }

        return $this->createUrl($filter);
    }

    public function getVariationUrl($id_label, $value_id, $filter_url = '')
    {
        $variations = $this->variations;
        if (array_key_exists($id_label, $variations)) {
            $variation = $variations[$id_label];
            $variation_values = [];
            if (!empty($variation['values'])) {
                $variation_values = $variation['values'];
            }
            if (array_key_exists($value_id, $variation_values)) {
                unset($variation_values[$value_id]);
            } else {
                $variation_value = ['id' => $value_id, 'id_label' => $id_label, 'filter_url' => $filter_url];
                $variation_values[$value_id] = $variation_value;
            }
            $variation['values'] = $variation_values;
            $variations[$id_label] = $variation;
        } else {
            $variation = ['id' => $id_label, 'to_title' => 'N', 'indexing' => 'N'];
            $variation_value = ['id' => $value_id, 'id_label' => $id_label, 'filter_url' => $filter_url];
            $variation['values'][$value_id] = $variation_value;
            $variations[$id_label] = $variation;
        }

        $filter = [];
        $i = 0;
        if ($variation['indexing'] == 'Y') {
            $variation['values'] = [];
            $variation_value = ['id' => $value_id, 'id_label' => $id_label, 'filter_url' => $filter_url];
            $variation['values'][$value_id] = $variation_value;
            $filter[0] = ['type' => 'variation', 'indexed' => 'Y', 'variation' => $variation];
            $i++;
        }
        if ($i < $this->indexedParamsCount) {
            $indexed_filter = $this->getIndexedFilter();
            foreach ($indexed_filter as $f) {
                if (($f['type'] == 'variation') && ($f['variation']['id'] == $id_label)) {
                    continue;
                }
                $filter[$i] = $f;
                $i++;
                if ($i >= $this->indexedParamsCount) {
                    break;
                }
            }
        }

        return $this->createUrl($filter);
    }

    /**
     * @return $this
     */
    public function setCategoryUrl($categoryUrl)
    {
        $this->categoryUrl = rtrim($categoryUrl, '/');

        return $this;
    }

    /**
     * @return $this
     */
    public function setIgnoreProducer($ignore)
    {
        $this->ignoreProducer = $ignore;

        return $this;
    }

    public function setFilterParams(\FilterParams $filterParams): FilterUrlGenerator
    {
        if ($this->filterParams !== $filterParams) {
            $this->filterParams = $filterParams;
            $this->prepareFilterParams();
        }

        return $this;
    }

    public function setParameters(array $parameters): void
    {
        $this->parameters = $parameters;
    }

    public function setSectionId($sectionId)
    {
        $this->sectionId = $sectionId;
    }

    protected function createUrlParts($filter): array
    {
        $url = [];
        $qs = [];
        $indexed = true;

        if (is_null($filter)) {
            $filter = $this->filter;
        }

        $producers = [];
        $parameters = [];
        $variations = [];
        $campaigns = [];
        $variationsSizeConvertion = [];
        $stores = [];
        $labels = [];
        $inStore = null;
        $priceRange = null;
        $search = null;
        foreach ($filter as $f) {
            switch ($f['type']) {
                case 'producers':
                    $producers = $f['producers'];
                    break;
                case 'parameter':
                    $parameter = $f['parameter'];
                    $parameters[$parameter['id']] = $parameter;
                    break;
                case 'variation':
                    $variation = $f['variation'];
                    $variations[$variation['id']] = $variation;
                    break;
                case 'campaigns':
                    $campaigns = $f['campaigns'];
                    break;
                case 'inStore':
                    $inStore = $f['inStore'];
                    break;
                case 'stores':
                    $stores = $f['stores'];
                    break;
                case 'variationsSizeConvertion':
                    $convertor = $f['convertor'];
                    $variationsSizeConvertion[$convertor['id']] = $convertor;
                    break;
                case 'labels':
                    $labels = $f['label_ids'];
                    break;
                case 'price':
                    $priceRange = $f['priceRange'];
                    break;
                case 'search':
                    $search = $f['value'];
                    break;
            }
        }

        if ($producers) {
            if ($this->section['producers_to_title'] == 'Y') {
                $url[] = implode('|', array_column($producers, 'filter_url'));
            } else {
                $qs['producerIds'] = array_column($producers, 'id');
            }
            if (($this->section['producers_indexing'] ?? 'N') == 'N') {
                $indexed = false;
            }
        }

        $parameters = array_filter(
            $parameters,
            function ($p) {
                return !empty($p['values']);
            }
        );
        if ($parameters) {
            $parameters_to_url = array_filter(
                $parameters,
                function ($p) {
                    return $p['to_title'] == 'Y';
                }
            );
            if ($parameters_to_url) {
                $parameter_filter_url = array_map(
                    function ($p) {
                        return implode('|', array_column($p['values'], 'filter_url'));
                    },
                    $parameters_to_url
                );
                $url = array_merge($url, $parameter_filter_url);
            }
            $parameters_to_qs = array_filter(
                $parameters,
                function ($p) {
                    return ($p['to_title'] ?? 'N') == 'N';
                }
            );
            if ($parameters_to_qs) {
                $parameter_qs = array_map(
                    function ($p) {
                        if (array_search($p['type'] ?? '', ['int', 'float'])) {
                            $qs_arr = [
                                'value' => join(' - ', array_map(function ($x) { return is_null($x) ? '*' : $x; }, array_column($p['values'], 'id'))),
                                'type' => $p['type'],
                            ];
                        } else {
                            $qs_arr = ['value' => array_column($p['values'], 'id')];
                        }

                        return $qs_arr;
                    },
                    $parameters_to_qs
                );
                $qs['parameters'] = $parameter_qs;
            }
            $parameters_no_indexing = array_filter(
                $parameters,
                function ($p) {
                    return ($p['indexing'] ?? 'N') == 'N';
                }
            );
            if ($parameters_no_indexing) {
                $indexed = false;
            }
        }

        $variations = array_filter(
            $variations,
            function ($v) {
                return !empty($v['values']);
            }
        );
        if ($variations) {
            $variations_to_url = array_filter(
                $variations,
                function ($v) {
                    return $v['to_title'] == 'Y';
                }
            );
            if ($variations_to_url) {
                $variation_filter_url = array_map(
                    function ($v) {
                        return implode('|', array_column($v['values'], 'filter_url'));
                    },
                    $variations_to_url
                );
                $url = array_merge($url, $variation_filter_url);
            }
            $variations_to_qs = array_filter(
                $variations,
                function ($v) {
                    return ($v['to_title'] ?? 'N') == 'N';
                }
            );
            if ($variations_to_qs) {
                $variation_qs = array_map(
                    function ($v) {
                        return ['value' => array_column($v['values'], 'id')];
                    },
                    $variations_to_qs
                );
                $qs['variations'] = $variation_qs;
            }
            $variations_no_indexing = array_filter(
                $variations,
                function ($v) {
                    return ($v['indexing'] ?? 'N') == 'N';
                }
            );
            if ($variations_no_indexing) {
                $indexed = false;
            }
        }

        if ($campaigns) {
            $qs['campaigns'] = array_combine($campaigns, $campaigns);
        }

        if ($inStore) {
            $qs['inStore'] = $inStore;
        }

        if ($stores) {
            $qs['storeIds'] = $stores;
        }

        if ($priceRange) {
            if (findModule(\Modules::COMPONENTS)) {
                if ($from = $priceRange->min()) {
                    $qs['priceRange']['from'] = $from;
                }

                if ($to = $priceRange->max()) {
                    $qs['priceRange']['to'] = $to;
                }
            } else {
                $qs['price'] = [
                    'value' => ($priceRange->min() ?? '*').' - '.($priceRange->max() ?? '*'),
                ];
            }
        }

        $variationsSizeConvertion = array_filter($variationsSizeConvertion, function ($p) {return !empty($p['values']); });
        if ($variationsSizeConvertion) {
            $convertors_to_url = array_filter(
                $variationsSizeConvertion,
                function ($p) {
                    return $p['to_title'] == 'Y';
                }
            );

            if ($convertors_to_url) {
                $convertors_to_url = array_map(
                    function ($p) {
                        return implode('|', array_column($p['values'], 'filter_url'));
                    },
                    $convertors_to_url
                );
                $url = array_merge($url, $convertors_to_url);
            }

            $convertors_to_qs = array_filter(
                $variationsSizeConvertion,
                function ($p) {
                    return ($p['to_title'] ?? 'N') == 'N';
                }
            );

            if ($convertors_to_qs) {
                $convertors_qs = array_map(
                    function ($p) {
                        return ['value' => array_column($p['values'], 'id')];
                    },
                    $convertors_to_qs
                );
                $qs['variationsSizeConvertion'] = $convertors_qs;
            }

            $convertors_no_indexing = array_filter(
                $variationsSizeConvertion,
                function ($v) {
                    return ($v['indexing'] ?? 'N') == 'N';
                }
            );

            if ($convertors_no_indexing) {
                $indexed = false;
            }
        }

        if ($labels) {
            foreach ($labels as $label) {
                $qs['labels'][$label] = $label;
            }
        }

        if ($search) {
            $qs['search'] = $search;
        }

        $url = (empty($url) ? '/' : '/'.implode('/', $url).'/');
        $qs = (empty($qs) ? '?' : '?'.http_build_query(['dynamic_filter' => $qs]).'&');

        return [$url, $qs, $indexed];
    }

    /**
     * @param array $sectionsParameters structure [[sectionId:int, parameters:[[id:int, value:int], ]], ]
     */
    public function getIndexedSectionsUrls(array $sectionsParameters)
    {
        $producerIds = [];
        $parametersValuesIds = [];

        foreach ($sectionsParameters as $sectionParameters) {
            foreach ($sectionParameters['parameters'] as $parameter) {
                if (!empty($parameter['id'])) {
                    $parametersValuesIds[] = $parameter['value'];
                }
            }

            foreach ($sectionParameters['producers'] ?? [] as $producerId) {
                $producerIds[] = $producerId;
            }
        }

        $parametersValues = sqlQueryBuilder()->select('pl.id,pl.id_parameter, pl.value, pl.filter_url')
            ->from('parameters_list', 'pl')
            ->where(Operator::inStringArray($parametersValuesIds, 'pl.id'))
            ->andWhere(Translation::coalesceTranslatedFields(ParametersListTranslation::class, ['value', 'filter_url']))
            ->execute()->fetchAllAssociativeIndexed();

        $producerValues = sqlQueryBuilder()->select('pr.id')
            ->from('producers', 'pr')
            ->where('pr.active="Y"')
            ->andWhere(Operator::inIntArray($producerIds, 'pr.id'))
            ->andWhere(Translation::coalesceTranslatedFields(ProducersTranslation::class, ['name', 'filter_url']))
            ->orderBy('pr.position, pr.name')
            ->execute()->fetchAllAssociative();

        foreach ($sectionsParameters as &$sectionParameters) {
            $urlFilter = [];

            if (!empty($sectionParameters['producers'])) {
                $urlFilter[] = [
                    'type' => 'producers',
                    /* 'indexed' => $this->section['producers_indexing'], */
                    'producers' => array_filter($producerValues, fn ($x) => in_array($x['id'], $sectionParameters['producers'])),
                ];
            }

            foreach ($sectionParameters['parameters'] as $parameter) {
                if (!empty($parameter['id'])) {
                    $parameterValue = $parametersValues[$parameter['value']];

                    $urlFilter[] = ['type' => 'parameter',
                        'indexed' => 'Y',
                        'parameter' => [
                            'id' => $parameter['id'],
                            'indexing' => 'Y',
                            'to_title' => 'Y',
                            'values' => [
                                $parameter['value'] => [
                                    'id' => $parameter['value'],
                                    'indexing' => 'Y',
                                    'to_title' => 'Y',
                                    'id_parameter' => $parameter['id'],
                                    'value' => $parameterValue['value'],
                                    'filter_url' => $parameterValue['filter_url'],
                                ],
                            ],
                        ], ];
                }
            }

            $section = $this->sectionTree->getSectionById($sectionParameters['sectionId']);

            $sectionData = sqlQueryBuilder()->select('s.id, s.name, s.filter_url, s.producers_indexing, s.producers_to_title')
                ->from('sections', 's')
                ->where(Operator::equals(['s.id' => $section->getId()]))
                ->execute()->fetchAssociative();

            if (!$sectionData) {
                $sectionData = [
                    'id' => 0,
                    'producers_to_title' => true,
                    'producers_indexing' => false,
                ];
            }

            $this->section = $sectionData;

            $this->setCategoryUrl($section->getUrl());

            $sectionParameters['url'] = $this->createUrl($urlFilter)['url'];
        }

        return $sectionsParameters;
    }
}
