<?php

declare(strict_types=1);

namespace KupShop\CatalogElasticBundle\Filters;

use Elastica\Aggregation\AbstractAggregation;
use KupShop\CatalogElasticBundle\Contracts\Identifiable;
use KupShop\CatalogElasticBundle\DataContext\AggregationContext;
use KupShop\CatalogElasticBundle\DataContext\ElasticFilterSpecContext;
use KupShop\CatalogElasticBundle\DataContext\ElasticFilterValuesContext;
use Symfony\Component\DependencyInjection\Attribute\AutoconfigureTag;

#[AutoconfigureTag(ElasticFilter::ELASTIC_FILTERS_TAG)]
abstract class ElasticFilter implements Identifiable
{
    /** @var string service tag */
    public const ELASTIC_FILTERS_TAG = 'kupshop.catalog-elastic.filter';

    /**
     * Apply filters to the Elasticsearch query.
     *
     * @see https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl.html
     */
    abstract public function applyFilters(ElasticFilterSpecContext $ctx): void;

    /**
     * Add aggregations to the Elasticsearch query.
     *
     * @return iterable<AbstractAggregation>
     *
     * @see https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations.html
     */
    public function getAggregations(AggregationContext $attributes): iterable
    {
        return [];
    }

    /**
     * Collect product counts and info for <code>\Filter::valuesCache</code>.
     *  = what <code>\Filter->getYourFilter($parameterId)</code> returns.
     *
     * @see \Filter::$valuesCache
     */
    public function collectValues(ElasticFilterValuesContext $ctx): void
    {
    }

    /**
     * @return bool Does the filter support the given filter param? (from \FilterParams)
     */
    public function supports(string $filterName): bool
    {
        return $filterName === static::filterIdentifier();
    }

    /**
     * @return int TaggedIterator priority - defaultPriorityMethod (set order of applied filters)
     */
    public static function priority(): int
    {
        return 0;
    }

    public static function filterIdentifier(): string
    {
        $classParts = explode('\\', static::class);

        return lcfirst(end($classParts));
    }

    public function supportsOrderBy(): bool
    {
        return false;
    }
}
