<?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\Controller\Page;

use Doctrine\ORM\EntityManagerInterface;
use Ferienpass\AdminBundle\Breadcrumb\Breadcrumb;
use Ferienpass\AdminBundle\Form\Filter\ConsentsFilter;
use Ferienpass\AdminBundle\Routing\Base58;
use Ferienpass\CoreBundle\ConsentManager\ConsentManager;
use Ferienpass\CoreBundle\ConsentManager\ConsentState;
use Ferienpass\CoreBundle\Entity\Consent;
use Ferienpass\CoreBundle\Entity\ConsentForm;
use Ferienpass\CoreBundle\Entity\User;
use Ferienpass\CoreBundle\Export\Consent\ConsentSheetExport;
use Ferienpass\CoreBundle\Repository\ConsentRepository;
use Ferienpass\CoreBundle\Repository\ParticipantRepositoryInterface;
use FOS\HttpCacheBundle\Configuration\InvalidatePath;
use Symfony\Bridge\Doctrine\Attribute\MapEntity;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\Extension\Core\Type\FormType;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Attribute\MapQueryParameter;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted;
use Symfony\Component\Uid\Uuid;
use Symfony\UX\Turbo\TurboBundle;

#[IsGranted('ROLE_ADMIN')]
#[Route('/einwilligungen')]
final class ConsentsController extends AbstractController
{
    #[Route('', name: 'admin_consents_index')]
    public function index(ConsentRepository $repository, Breadcrumb $breadcrumb): Response
    {
        $qb = $repository->createQueryBuilder('i');
        $qb->leftJoin('i.user', 'user');
        $qb->orderBy('i.createdAt', 'DESC');

        return $this->render('@FerienpassAdmin/page/consents/index.html.twig', [
            'qb' => $qb,
            'filterType' => ConsentsFilter::class,
            'searchable' => ['user.firstname', 'user.lastname'],
            'breadcrumb' => $breadcrumb->generate('tools.title', 'signatures.title'),
        ]);
    }

    #[Route('/{id}/löschen', name: 'admin_consents_delete', requirements: ['id' => '\d+'])]
    #[InvalidatePath('/admin/einwilligungen')]
    public function delete(Consent $item, Request $request, EntityManagerInterface $entityManager): Response
    {
        $this->denyAccessUnlessGranted('delete', $item);

        $form = $this->createForm(FormType::class, options: [
            'action' => $this->generateUrl('admin_consents_delete', ['id' => $item->getId()]),
        ]);

        $form->handleRequest($request);
        if ($form->isSubmitted() && $form->isValid()) {
            $deletedId = $item->getId();

            $entityManager->remove($item);
            $entityManager->flush();

            if (TurboBundle::STREAM_FORMAT === $request->getPreferredFormat()) {
                // If the request comes from Turbo, set the content type as text/vnd.turbo-stream.html and only send the HTML to update
                $request->setRequestFormat(TurboBundle::STREAM_FORMAT);

                return $this->renderBlock('@FerienpassAdmin/page/consents/index.html.twig', 'deleted_stream', ['id' => $deletedId]);
            }

            return $this->redirectToRoute('admin_consents_index');
        }

        return $this->render('@FerienpassAdmin/page/consents/delete.html.twig', [
            'item' => $item,
            'form' => $form,
        ]);
    }

    #[Route('/{id}/widerrufen', name: 'admin_consents_revoke', requirements: ['id' => '\d+'])]
    #[InvalidatePath('/admin/einwilligungen')]
    public function revoke(Consent $item, Request $request, EntityManagerInterface $entityManager): Response
    {
        $this->denyAccessUnlessGranted('revoke', $item);

        $form = $this->createForm(FormType::class, options: [
            'action' => $this->generateUrl('admin_consents_revoke', ['id' => $item->getId()]),
        ]);

        $form->handleRequest($request);
        if ($form->isSubmitted() && $form->isValid()) {
            $item->revoke();

            $entityManager->flush();

            //            if (TurboBundle::STREAM_FORMAT === $request->getPreferredFormat()) {
            //                // If the request comes from Turbo, set the content type as text/vnd.turbo-stream.html and only send the HTML to update
            //                $request->setRequestFormat(TurboBundle::STREAM_FORMAT);
            //
            //                return $this->renderBlock('@FerienpassAdmin/page/signatures/index.html.twig', 'updated_stream', ['item' => $item]);
            //            }

            return $this->redirectToRoute('admin_consents_index');
        }

        return $this->render('@FerienpassAdmin/page/consents/revoke.html.twig', [
            'item' => $item,
            'form' => $form,
        ]);
    }

    #[Route('/{id}/dokument', name: 'admin_consents_sheet', requirements: ['id' => '\d+'])]
    public function sheet(Consent $item, ConsentSheetExport $export): Response
    {
        $this->denyAccessUnlessGranted('view', $item);

        $path = $export->generate($item);

        return $this->file($path, \sprintf('einwilligung-%d.pdf', $item->getId()));
    }

    #[Route('/status/{form}/{user}/{participant}', name: 'admin_consents_details', defaults: ['participant' => null])]
    // The {uuid} segment now carries the Consent's base58 UUID; the legacy
    // route preserves old integer-id links. Resolution branches below.
    #[Route('/{uuid}', name: 'admin_consents_show', requirements: ['uuid' => Base58::UUID])]
    #[Route('/{uuid}', name: 'admin_consents_show_legacy', requirements: ['uuid' => '\d+'])]
    public function show(
        ConsentManager $consentManager,
        ParticipantRepositoryInterface $participantRepository,
        ConsentRepository $consentRepository,
        #[MapEntity(mapping: ['form' => 'id'])]
        ?ConsentForm $form = null,
        #[MapEntity(mapping: ['user' => 'id'])]
        ?User $user = null,
        ?string $participant = null,
        #[MapQueryParameter]
        ?string $token = null,
        ?string $uuid = null,
    ): Response {
        $consent = null;
        if (null !== $uuid) {
            // base58/RFC4122 UUID (canonical) vs legacy integer id.
            try {
                $consent = $consentRepository->findOneBy(['uuid' => Uuid::fromString($uuid)]);
            } catch (\InvalidArgumentException) {
                $consent = $consentRepository->find((int) $uuid);
            }
        }

        if ($consent instanceof Consent) {
            $state = new ConsentState($consent->getConsentForm(), $consent, $consent->getParticipant(), $consent->getUser());
        } elseif (null !== $form && null !== $user) {
            $participantEntity = $participant ? $participantRepository->findByUuid($participant) : null;
            $state = $consentManager->findState($form, $user, $participantEntity);
        } else {
            throw $this->createNotFoundException();
        }

        if ($token) {
            $state->setConsentToken($token);
        }

        return $this->render('@FerienpassAdmin/page/consents/show.html.twig', [
            'state' => $state,
        ]);
    }
}
