<?php

declare(strict_types=1);

/*
 * Chill is a software for social workers
 *
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */

namespace Chill\MainBundle\Templating\Listing;

use Chill\MainBundle\Templating\Entity\UserRender;
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
use Symfony\Component\PropertyAccess\PropertyPathInterface;
use Symfony\Contracts\Translation\TranslatorInterface;

final readonly class FilterOrderGetActiveFilterHelper
{
    public function __construct(
        private TranslatorInterface $translator,
        private PropertyAccessorInterface $propertyAccessor,
        private UserRender $userRender,
    ) {}

    /**
     * Return all the data required to display the active filters.
     *
     * @return array<array{label: string, value: string, position: string, name: string}>
     */
    public function getActiveFilters(FilterOrderHelper $filterOrderHelper): array
    {
        $result = [];

        if ($filterOrderHelper->hasSearchBox() && '' !== $filterOrderHelper->getQueryString()) {
            $result[] = ['label' => '', 'value' => $filterOrderHelper->getQueryString(), 'position' => FilterOrderPositionEnum::SearchBox->value, 'name' => 'q'];
        }

        foreach ($filterOrderHelper->getDateRanges() as $name => ['label' => $label]) {
            $base = ['position' => FilterOrderPositionEnum::DateRange->value, 'name' => $name, 'label' => (string) $label];

            if (null !== ($from = $filterOrderHelper->getDateRangeData($name)['from'] ?? null)) {
                $result[] = ['value' => $this->translator->trans('filter_order.by_date.From', ['from_date' => $from]), ...$base];
            }
            if (null !== ($to = $filterOrderHelper->getDateRangeData($name)['to'] ?? null)) {
                $result[] = ['value' => $this->translator->trans('filter_order.by_date.To', ['to_date' => $to]), ...$base];
            }
        }

        foreach ($filterOrderHelper->getCheckboxes() as $name => ['choices' => $choices, 'trans' => $trans]) {
            $translatedChoice = array_combine($choices, [...$trans]);
            foreach ($filterOrderHelper->getCheckboxData($name) as $keyChoice) {
                $result[] = ['value' => $this->translator->trans($translatedChoice[$keyChoice]), 'label' => '', 'position' => FilterOrderPositionEnum::Checkboxes->value, 'name' => $name];
            }
        }

        foreach ($filterOrderHelper->getEntityChoices() as $name => ['label' => $label, 'class' => $class, 'choices' => $choices, 'options' => $options]) {
            foreach ($filterOrderHelper->getEntityChoiceData($name) as $selected) {
                if (is_callable($options['choice_label'])) {
                    $value = call_user_func($options['choice_label'], $selected);
                } elseif ($options['choice_label'] instanceof PropertyPathInterface || is_string($options['choice_label'])) {
                    $value = $this->propertyAccessor->getValue($selected, $options['choice_label']);
                } else {
                    if (!$selected instanceof \Stringable) {
                        throw new \UnexpectedValueException(sprintf("we are not able to transform the value of %s to a string. Implements \\Stringable or add a 'choice_label' option to the filterFormBuilder", $selected::class));
                    }

                    $value = (string) $selected;
                }

                $result[] = ['value' => $this->translator->trans($value), 'label' => $label, 'position' => FilterOrderPositionEnum::EntityChoice->value, 'name' => $name];
            }
        }

        foreach ($filterOrderHelper->getUserPickers() as $name => ['label' => $label, 'options' => $options]) {
            foreach ($filterOrderHelper->getUserPickerData($name) as $user) {
                $result[] = ['value' => $this->userRender->renderString($user, []), 'label' => (string) $label, 'position' => FilterOrderPositionEnum::UserPicker->value, 'name' => $name];
            }
        }

        foreach ($filterOrderHelper->getSingleCheckbox() as $name => ['label' => $label]) {
            if (true === $filterOrderHelper->getSingleCheckboxData($name)) {
                $result[] = ['label' => '', 'value' => $this->translator->trans($label), 'position' => FilterOrderPositionEnum::SingleCheckbox->value, 'name' => $name];
            }
        }

        return $result;
    }
}
