<?php

namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\Routing\Requirement\Requirement;
use Symfony\Component\Routing\Attribute\Route;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bridge\Twig\Mime\TemplatedEmail;
use Symfony\Component\Mime\Address;
use Symfony\Component\Mailer\MailerInterface;
use Symfony\Component\Mime\Email;

use App\Entity\Slot;
use App\Entity\Party;
use App\Entity\Event;
use App\Entity\Participation;
use App\Repository\SlotRepository;
use App\Repository\ParticipationRepository;
use App\Form\ParticipationType;

final class ParticipationController extends AbstractController
{

    #[Route('/cancel/{id}', name: 'app_participation_cancel', requirements: ['id' => Requirement::UUID_V7], methods: ['GET', 'POST'])]
    public function cancel(?Participation $participation, Request $request, EntityManagerInterface $manager, ParticipationRepository $repository): Response
    {
        if (!$participation) {
            // TGCM, ça ressemble à un UUID, mais y'a rien derrière
            $this->addFlash('danger', 'Participation inexistante !');
            return $this->redirectToRoute('app_main');
        }

        $redirectPath = 'app_main';
        $user = $this->getUser();
        if ($user && $user->getEmail() == $participation->getParticipantEmail()) {
            // L'utilisateur qui annule est connecté, la page de redirection est sa liste de parties
            $redirectPath = 'app_profile_participations';
        }

        // TODO: prendre en charge l'annulation en une fois de réservations de groupe
        // Détecter si d'autres réservations avec la même adresse mail existent -> présnter dans un tableau annexe
        $otherParticipations = $repository->findAllByEmail($participation->getParticipantEmail());
        if (count($otherParticipations)>1) {
            // Plusieurs participations avec la même adresse sur cette partie...  OUI, MAIS C'EST PAS LE BON REPO !!!! IL FAUT BRIDER AUX PARTIES !!!!
        }

        $form = $this->createFormBuilder(FormType::class)->getForm();
        $form->handleRequest($request);
        if ($form->isSubmitted() && $form->isValid()) {
            $game = $participation->getParty()->getGame()->getName();
            $gameDate = $participation->getParty()->getStartOn();
            $gameDate->setTimezone(new \DateTimeZone($_ENV['APP_TZ']));
            $gameDateStr = $gameDate->format('d/m/y H:i');
            $manager->remove($participation);
            $manager->flush();
            $this->addFlash('info', 'Votre participation à '.$game.' du '.$gameDateStr.' a bien été annulée.');
            return $this->redirectToRoute($redirectPath);
        }

        return $this->render('participation/cancel.html.twig' , [
            'form' => $form,
            'participation' => $participation,
            'redirectPath' => $redirectPath,
        ]);

    }

    #[Route('/cancel/{id}/direct', name: 'app_participation_cancel_direct', requirements: ['id' => Requirement::UUID_V7], methods: ['GET', 'POST'])]
    public function cancelByAdmin(?Participation $participation, Request $request, EntityManagerInterface $manager): Response
    {
        if (!$this->isGranted('ROLE_MANAGER')) {
            $this->addFlash('danger', 'Seuls les gestionnaires et les admins sont autorisés à utiliser cette fonction.');
            return $this->redirectToRoute('app_main');
        }

        if (!$participation) {
            // TGCM, ça ressemble à un UUID, mais y'a rien derrière
            $this->addFlash('danger', 'Participation inexistante !');
            return $this->redirectToRoute('app_main');
        }

        $manager->remove($participation);
        $manager->flush();

        $referer = $request->headers->get('referer'); 
        return $this->redirect($referer);

    }

    // afficher les détails d'une partie à partir d'un slot et permettre l'inscription
    #[Route('/party/participation/{id}', name: 'app_participation', requirements: ['id' => '\d+'], methods: ['GET', 'POST'])]
    public function partiticipation(?Slot $slot, Request $request, SlotRepository $slotRepository, EntityManagerInterface $manager, MailerInterface $mailer): Response
    {
        $party = $slot->getParty();
        if (!$party) {
            $this->addFlash('danger', 'Aucune partie associée à ce slot !');
            $referer = $request->headers->get('referer'); 
            return $this->redirect($referer);
        }

        $user=$this->getUser();
        // Si un utilisateur est connecté et que ce n'est ni un admin, ni un gestionnaire, ni le MJ de cette partie
        if ($user) {
            $roles = $user->getRoles();
            // Gestionnaire ou admin -> annuler l'user
            if (in_array("ROLE_MANAGER", $roles) || in_array("ROLE_ADMIN", $roles)) {
                $user = null;
            } elseif (in_array("ROLE_STAFF", $roles) && $party->getGamemaster() == $user->getLinkToGamemaster()) {
                $user = null;
            }
        }

        // Préparation du formulaire de participation
        $participation = new Participation();
        $participation->setParty($party);
        if ($user) {
            $participation->setParticipantName($user->getFullName());
            $participation->setParticipantEmail($user->getEmail());
            $participation->setParticipantPhone($user->getPhone()); 
        }
        
        $form = $this->createForm(ParticipationType::class, $participation);
        
        // Traitement des entrées du formulaire
        $form->handleRequest($request);
        if ($form->isSubmitted() && $form->isValid()) {

            // Récupérer le tableau des accompagnant.e envoyé
            $partyMore = $request->request->all('party_more');
            // Garder uniquement les noms non vides
            $partyMore = array_filter($partyMore, fn($name) => trim($name) !== '');
            // Réindexer pour avoir un tableau propre (0, 1, 2, ...)
            $partyMore = array_values($partyMore);

            // On contrôle qu'il y a encore de la place, sinon -> erreur
            if ($party->getSeatsLeft() < 1) {
                if ($party->getSeatsLeft() > 0) {
                    $this->addFlash('danger', 'Il n\'y a pas assez de places pour vous accueillir sur cette partie.');
                } else {
                    $this->addFlash('danger', 'Il n\'y a plus de places pour vous accueillir sur cette partie.');
                }
            } else {
                $reservationsCounter = 1;

                // On enregistre dans la base
                $manager->persist($participation);
                $manager->flush();
                
                // Envoyer un mail
                // Maintenant uniquement pour avoir l'ID
                $email = (new TemplatedEmail())
                    ->from(new Address($_ENV['CONTACT_EMAIL'], $_ENV['CONTACT_NAME']))
                    ->to((string) $participation->getParticipantEmail())
                    ->subject('Votre réservation pour '.$party->getGame()->getName())
                    ->htmlTemplate('participation/booking.email.html.twig')
                    ->textTemplate('participation/booking.email.txt.twig')
                    ->context([
                        'participation' => $participation,
                    ]);
                $mailer->send($email);

                // On traite les accompagnant.e.s
                foreach ($partyMore as $companion) {
                    $newParticipation = new Participation;
                    $newParticipation->setParty($participation->getParty());
                    $newParticipation->setParticipantName($companion);
                    $newParticipation->setParticipantEmail($participation->getParticipantEmail());
                    $newParticipation->setParticipantPhone($participation->getParticipantPhone());
                    $manager->persist($newParticipation);
                    $manager->flush();                   
                    $email = (new TemplatedEmail())
                        ->from(new Address($_ENV['CONTACT_EMAIL'], $_ENV['CONTACT_NAME']))
                        ->to((string) $participation->getParticipantEmail())
                        ->subject('Votre réservation pour '.$party->getGame()->getName())
                        ->htmlTemplate('participation/booking.email.html.twig')
                        ->textTemplate('participation/booking.email.txt.twig')
                        ->context([
                            'participation' => $newParticipation,
                        ]);
                    $mailer->send($email);
                    $reservationsCounter++;
                }

                // On informe
                if ($reservationsCounter > 1) {
                    $this->addFlash('success', $reservationsCounter.' réservations enregistrées.');
                } else {
                    $this->addFlash('success', 'Réservation enregistrée.');
                }
            }

            //$this->redirectToRoute('app_main_booking', ['id' => $party->getEvent()->getId()]);
            $referer = $request->headers->get('referer'); 
            return $this->redirect($referer);

        }
        // Affichage de la modale
        return $this->render('participation/_modal.add.html.twig', [
            'party' => $party,
            'slot' => $slot,
            'form' => $form,
            'pathController' => 'app_participation'
        ]);

    }
}
