<?php

declare(strict_types=1);

namespace MonsieurBiz\SyliusSearchPlugin\Factory\ResultSet;

use Elastica\ResultSet as ElasticaResultSet;
use MonsieurBiz\SyliusSearchPlugin\Model\Document\Filter;
use MonsieurBiz\SyliusSearchPlugin\Model\Document\FilterAwareInterface;
use MonsieurBiz\SyliusSearchPlugin\Model\Document\FilterInterface;
use MonsieurBiz\SyliusSearchPlugin\Model\Document\FilterValue;
use MonsieurBiz\SyliusSearchPlugin\Model\Document\ResultSetFilter;

class MainTaxonFilterFactory implements MainTaxonFilterFactoryInterface
{
    public function create(ElasticaResultSet $resultSet = null): FilterAwareInterface
    {
        $filter = new ResultSetFilter();
        if (null !== $resultSet) {
            $filter->setFilter($this->buildMainTaxonFilter($resultSet));
        }

        return $filter;
    }

    private function buildMainTaxonFilter(ElasticaResultSet $resultSet): ?FilterInterface
    {
        $aggregations = $resultSet->getAggregations();
        $taxonAggregation = $aggregations['mainTaxon'] ?? null;

        if (null === $taxonAggregation || $taxonAggregation['doc_count'] <= 0) {
            return null;
        }

        $filter = new Filter('main_taxon', 'monsieurbiz_searchplugin.filters.taxon_filter', $taxonAggregation['doc_count']);

        // Get main taxon code in aggregation
        $taxonCodeBuckets = $taxonAggregation['codes']['buckets'] ?? [];
        foreach ($taxonCodeBuckets as $taxonCodeBucket) {
            if (0 === $taxonCodeBucket['doc_count']) {
                continue;
            }
            $taxonCode = $taxonCodeBucket['key'];
            $taxonName = null;

            // Get main taxon level in aggregation
            $taxonLevelBuckets = $taxonCodeBucket['levels']['buckets'] ?? [];
            foreach ($taxonLevelBuckets as $taxonLevelBucket) {
                // Get main taxon name in aggregation
                $taxonNameBuckets = $taxonLevelBucket['names']['buckets'] ?? [];
                foreach ($taxonNameBuckets as $taxonNameBucket) {
                    $taxonName = $taxonNameBucket['key'];
                    $label = $taxonName ?? $taxonCode;
                    $filterValue = new FilterValue($label, \urlencode($label), $taxonCodeBucket['doc_count']);
                    $filter->addValue($filterValue);

                    break 2;
                }
            }
        }

        // Put taxon filter in first if contains value
        if (count($filter->getValues()) > 0) {
            return $filter;
        }

        return null;
    }
}
