<?php

namespace Daylight\Core\Modules\Search\Entities;

use Daylight\Core\Modules\Multilingualism\Translations;
use Illuminate\Support\Collection;

class Facet
{
    public ?array $range = null;

    public array $options;

    public function __construct(private SearchResult $searchResult, public string $property, public string $name)
    {
        $range = $this->searchResult->originalResults
            ->filter(function ($result) {
                return isset($result['facetStats'][$this->property]);
            })
            ->filter(fn ($result) => isset($result['facetStats'][$this->property]))
            ->reverse()
            ->first();

        if ($range) {
            $this->range = $range['facetStats'][$this->property];
        }
    }

    public function getFilters(bool $useTranslation = true): Collection
    {
        return collect(collect($this->searchResult->originalResults)
            ->pluck('facetDistribution')
            ->flattenKeepKeys()
            ->toArray()[$this->property])
            ->mapWithKeys(function ($amount, $filter) use ($useTranslation) {
                $activeFiltersForProperty = $this->searchResult->activeFilters[$this->property] ?? [];

                $translationProperty = in_array($this->property, ['brand', 'price'])
                    ? $this->property
                    : 'attributeValues';

                return [
                    $filter => [
                        'name' => is_int($filter) && $useTranslation
                            ? Translations::all()->get($translationProperty)->get($filter)?->get(app()->getLocale()) ?? $filter
                            : $filter,
                        'amount' => $amount,
                        'active' => in_array($filter, $activeFiltersForProperty),
                    ],
                ];
            })
            ->map(function ($attribute, $key) {
                return new Filter($this->property, $key, $attribute['name'], $attribute['amount'], $attribute['active']);
            })
            ->sortBy(function (Filter $filter) {
                $key = $filter->key;
                $name = $filter->name;

                if ($key === 'true' || $key === true || $name === 'true') {
                    return [0, 0, $name];
                }
                if ($key === 'false' || $key === false || $name === 'false') {
                    return [0, 1, $name];
                }

                $numericValue = null;
                if (preg_match('/^(\d+(?:\.\d+)?)/', $name, $matches)) {
                    $numericValue = (float) $matches[1];
                }

                if ($numericValue !== null) {
                    return [1, $numericValue, $name];
                }

                if (is_numeric($key)) {
                    return [1, (float) $key, $name];
                }

                if (is_numeric($name)) {
                    return [1, (float) $name, $name];
                }

                return [2, strtolower($name), $name];
            })
            ->values();
    }

    public function toArray(): array
    {
        return [
            'property' => $this->property,
            'name' => $this->name,
            'range' => $this->range,
            'filters' => $this->getFilters()->toArray(),
            'options' => $this->options,
        ];
    }
}
