<?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\Offer;

use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\Query\Expr\Join;
use Doctrine\ORM\QueryBuilder;
use Ferienpass\AdminBundle\Form\Filter\AbstractFilterType;
use Ferienpass\AdminBundle\Form\Filter\AsSubFilter;
use Ferienpass\CoreBundle\Entity\Host;
use Ferienpass\CoreBundle\Entity\User;
use Ferienpass\CoreBundle\Repository\HostRepository;
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: 'host', section: 'base', priority: 90, views: ['admin_offers_index', 'admin_payments_unpaid', 'admin_payments_overpaid'])]
class HostFilter extends AbstractFilterType
{
    public function __construct(private readonly Security $security, private readonly HostRepository $hosts)
    {
    }

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

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

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

                if (!$this->security->isGranted('ROLE_ADMIN')) {
                    $qb->innerJoin('h.memberAssociations', 'm', Join::WITH, 'm.user = :user')->setParameter('user', $this->security->getUser());
                }

                return $qb->orderBy('h.name');
            },
            'choice_value' => static fn (?Host $entity) => $entity?->getAlias(),
            'choice_label' => 'name',
            'placeholder' => 'Alle',
            'multiple' => false,
            'autocomplete' => true,
        ]);
    }

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

        if ($form->isEmpty() && $this->security->isGranted('ROLE_ADMIN')) {
            return;
        }

        if ($form->isEmpty() && !$this->security->isGranted('ROLE_ADMIN')) {
            if (!($user = $this->security->getUser()) instanceof User) {
                $qb->where('i.id = 0');

                return;
            }

            $hosts = $this->hosts->findByUser($user);

            switch ($viewId) {
                case 'admin_payments_unpaid':
                case 'admin_payments_overpaid':
                    $qb->innerJoin('o.hosts', 'h_filter_default')->andWhere('h_filter_default IN (:hosts)')->setParameter('hosts', $hosts);
                    break;
                default:
                    $qb->andWhere('h IN (:hosts)')->setParameter('hosts', $hosts);
            }

            return;
        }

        $k = $form->getName();
        $v = $form->getData();

        switch ($viewId) {
            case 'admin_payments_unpaid':
            case 'admin_payments_overpaid':
                $qb->innerJoin('o.hosts', 'h_filter')->andWhere('h_filter IN (:q_'.$k.')')->setParameter('q_'.$k, $v);
                break;
            default:
                $qb->andWhere('h IN (:q_'.$k.')')->setParameter('q_'.$k, $v);
        }
    }

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