<?php

declare(strict_types=1);

/*
 * This file is part of the Ferienpass package.
 *
 * (c) Richard Henkenjohann <richard@ferienpass.online>
 *
 * For more information visit the project website <https://ferienpass.online>
 * or the documentation under <https://docs.ferienpass.online>.
 */

namespace Ferienpass\AdminBundle\Form\Filter;

use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\QueryBuilder;
use Ferienpass\CoreBundle\Entity\Edition;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Bundle\SecurityBundle\Security;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Contracts\Translation\TranslatableInterface;

#[AsSubFilter(key: 'edition', section: 'base', priority: 90, views: ['admin_offers_index', 'admin_hosts_index', 'admin_attendances_index', 'admin_participants_attendances'])]
class EditionFilter extends AbstractFilterType
{
    public function __construct(private readonly Security $security)
    {
    }

    public function getParent(): string
    {
        return EntityType::class;
    }

    public function shallDisplay(?string $viewId = null): bool
    {
        if ('admin_offers_index' === $viewId) {
            return $this->security->isGranted('ROLE_ADMIN');
        }

        return true;
    }

    public function configureOptions(OptionsResolver $resolver): void
    {
        $resolver->setDefaults([
            'class' => Edition::class,
            'query_builder' => function (EntityRepository $er): QueryBuilder {
                $qb = $er->createQueryBuilder('e');

                if (!$this->security->isGranted('ROLE_ADMIN')) {
                    $qb->where('e.archived <> 1');
                }

                return $qb->orderBy('e.name');
            },
            'choice_value' => static fn (?Edition $entity) => $entity?->getAlias(),
            'choice_label' => 'name',
            'placeholder' => '-',
            'multiple' => false,
        ]);
    }

    public function apply(QueryBuilder $qb, FormInterface $form): void
    {
        $viewId = $form->getParent()->getConfig()->getOption('view_id');
        $k = $form->getName();
        $v = $form->getData();

        if ($form->isEmpty()) {
            if ('admin_offers_index' === $viewId && !$this->security->isGranted('ROLE_ADMIN')) {
                $qb->andWhere('i.edition IN (SELECT edition_f FROM '.Edition::class.' edition_f WHERE edition_f.archived <> 1)');
            }

            return;
        }

        switch ($viewId) {
            case 'admin_hosts_index':
            case 'admin_attendances_index':
            case 'admin_participants_attendances':
                $qb->andWhere('o.edition = :q_'.$k)->setParameter('q_'.$k, $v);
                break;
            default:
                $qb->andWhere('i.edition = :q_'.$k)->setParameter('q_'.$k, $v);
        }
    }

    protected function getHumanReadableValue(FormInterface $form): string|TranslatableInterface|null
    {
        return $form->getData()?->getName();
    }
}
