<?php

namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
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\partyRequest;
use App\Entity\Party;
use App\Entity\Participation;
use App\Repository\EventRepository;
use App\Repository\SlotRepository;
use App\Entity\Event;
use App\Entity\Gamemaster;

final class ManageController extends AbstractController
{
    #[Route('/manage', name: 'app_manage')]
    public function manage(EventRepository $repository): Response
    {

        // Récupérer la liste des événements visibles
        $events = $repository->findEventsToCome(false);
        if (!$events) {
            $this->addFlash('info', 'Aucun d\'événement n\'est plannifié pour le moment.');
            return $this->redirectToRoute('app_main');
        }
        $event = $events[0];

        return $this->render('manage/manage.html.twig', [
            'event' => $event,
            'events' => $events
        ]);
    }

    #[Route('/manage/{id}', name: 'app_manage_planning', requirements: ['id' => Requirement::UUID_V7], methods: ['GET', 'POST'])]
    public function managePlanning(?Event $event, EventRepository $repository): Response
    {
        // Contrôler qu'un événement est bien ok
        if (!$event) {
            $this->addFlash('danger', 'Événement inconnu !');
            return $this->redirectToRoute('app_manage');
        }

        // Récupérer la liste des événements visibles
        $events = $repository->findEventsToCome(false);

        return $this->render('manage/manage.html.twig', [
            'event' => $event,
            'events' => $events
        ]);
    }

    #[Route('/manage/{id}/list', name: 'app_manage_party_list', requirements: ['id' => Requirement::UUID_V7], methods: ['GET', 'POST'])]
    public function managePartyList(?Event $event, EventRepository $repository): Response
    {
        // Contrôler qu'un événement est bien ok
        if (!$event) {
            $this->addFlash('danger', 'Événement inconnu !');
            return $this->redirectToRoute('app_manage');
        }

        // Récupérer la liste des événements visibles
        $events = $repository->findEventsToCome(false);

        return $this->render('manage/list.html.twig', [
            'event' => $event,
            'events' => $events
        ]);
    }

    #[Route('/manage/{id}/booking', name: 'app_manage_booking', requirements: ['id' => Requirement::UUID_V7], methods: ['GET', 'POST'])]
    public function manageBooking(?Event $event, EventRepository $repository): Response
    {
        // Contrôler qu'un événement est bien ok
        if (!$event) {
            $this->addFlash('danger', 'Événement inconnu !');
            return $this->redirectToRoute('app_manage');
        }

        // Récupérer la liste des événements visibles
        $events = $repository->findEventsToCome(false);

        return $this->render('manage/booking.html.twig', [
            'event' => $event,
            'events' => $events
        ]);
    }

    #[Route('/manage/{id}/request', name: 'app_manage_request', requirements: ['id' => Requirement::UUID_V7], methods: ['GET', 'POST'])]
    public function manageRequest(?Event $event, EventRepository $repository): Response
    {
        // Contrôler qu'un événement est bien ok
        if (!$event) {
            $this->addFlash('danger', 'Événement inconnu !');
            return $this->redirectToRoute('app_manage');
        }

        // Contrôler que l'événement accepte bien les requêtes
        if (!$event->isEveryoneCanAskForGame()) {
            $this->addFlash('danger', 'Cet événement ne prend pas en charge les demandes de parties.');
            return $this->redirectToRoute('app_manage_planning', ['id' => $event->getId()]);            
        }

        // Récupérer la liste des événements visibles
        $events = $repository->findEventsToCome(false);

        return $this->render('manage/request.html.twig', [
            'event' => $event,
            'events' => $events
        ]);
    }

    #[Route('/manage/request/{id}/delete', name: 'app_manage_request_delete', requirements: ['id' => Requirement::UUID_V7], methods: ['GET'])]
    public function requestDelete(?partyRequest $partyRequest, EntityManagerInterface $manager): Response
    {
        // la requête existe-t-elle bien ?
        if (!$partyRequest) {
            $this->addFlash('danger', 'Demande inconnue !');
            return $this->redirectToRoute('app_manage');
        }

        $event = $partyRequest->getEvent();
        $state = $partyRequest->getState();
        // La requête a-t-elle obtenue une réponse ?
        if ($state['code'] == "WAIT") {
            $this->addFlash('danger', 'Vous devez apporter une réponse avant de supprimer !');
            return $this->redirectToRoute('app_manage_request', ['id' => $event->getId()]);
        }

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

        $this->addFlash('success', 'Demande supprimée !');
        return $this->redirectToRoute('app_manage_request', ['id' => $event->getId()]);
    }

    #[Route('/manage/request/{id}/accept', name: 'app_manage_request_accept', requirements: ['id' => Requirement::UUID_V7], methods: ['GET', 'POST'])]
    public function requestAccept(?partyRequest $partyRequest, Request $request, EntityManagerInterface $manager, MailerInterface $mailer, EventRepository $repository, SlotRepository $slotRepository): Response
    {
        // Fonction inspirée de 'app_party_add' du controlleur "App\Controller\PartyController"
        // TODO: créer une seule fonction
        // PRIO: low

        $user = $this->getUser();

        // la requête existe-t-elle bien ?
        if (!$partyRequest) {
            $this->addFlash('danger', 'Demande inconnue !');
            return $this->redirectToRoute('app_manage');
        }

        $event = $partyRequest->getEvent();
        $state = $partyRequest->getState();
        // La requête est-elle en attente d'une réponse ?
        if (!$state['code'] == "WAIT") {
            $this->addFlash('danger', 'Une réponse a déjà été apportée : '.$state['name'].'.');
            return $this->redirectToRoute('app_manage_planning', ['id' => $event->getId()]);
        }

        // Traiter, on complète déjà ce qu'on connaît
        $party = new Party();
        $party->setGamemaster($partyRequest->getGamemasterChoosen());
        $party->setGame($partyRequest->getGameChoosen());
        $party->setEvent($partyRequest->getEvent());
        $party->setMinParticipants($_ENV['APP_DEFAULT_MIN_PARTICIPANTS']);
        $party->setMaxParticipants($_ENV['APP_DEFAULT_MAX_PARTICIPANTS']);
        $party->setSubmitter($user);
        $party->setSubmittedDate(new \Datetime('now'));
        $party->setValidated(true);

        // Création d'un formulaire vierge
        $form = $this->createFormBuilder(FormType::class)->getForm();
        $form->handleRequest($request);
        if ($form->isSubmitted() && $form->isValid()) {
            // On reçoit du formulaire un array de Slot pour poser la partie
            $slotsString = $request->request->get('party_slots');
            $new_slots = explode("|", $slotsString);
            // On ajoute les slots à la partie
            foreach($new_slots as $add_this_slot) {
                $add_this_slot_obj = $slotRepository->findById($add_this_slot);
                $party->addSlot($add_this_slot_obj);
            }
            // On ajoute les horaires à la partie
            $party->setStartOn(clone $party->getSlots()[0]->getStartOn());
            $party->setEndOn(clone $party->getSlots()->last()->getEndOn());

            // On enregistre la partie
            $manager->persist($party);

            // On met à jour la demande
            $partyRequest->setModerator($user);
            $partyRequest->setModOnDate(new \Datetime('now'));
            $partyRequest->setAccepted(true);
            $manager->persist($partyRequest);

            // On crée une participation pour le demandeur
            $participation = new Participation();
            $participation->setParty($party);
            $participation->setParticipantName($partyRequest->getRequester()->getFullName());
            $participation->setParticipantEmail($partyRequest->getRequester()->getEmail());
            $participation->setParticipantPhone($partyRequest->getRequester()->getPhone());
            $manager->persist($participation);

            // Et on sync dans la BDD
            $manager->flush();

            // On préviens par mail
            $email = (new TemplatedEmail())
                ->from(new Address($_ENV['CONTACT_EMAIL'], $_ENV['CONTACT_NAME']))
                ->to((string) $partyRequest->getRequester()->getEmail())
                ->subject('En réponse à votre demande pour '.$party->getEvent()->getName())
                ->htmlTemplate('manage/request/accepted.email.html.twig')
                ->textTemplate('manage/request/accepted.email.txt.twig')
                ->context([
                    'participation' => $participation,
                    'partyRequest' => $partyRequest,
                    'party' => $party
                ]);
            $mailer->send($email);

            // On a terminé !
            $this->addFlash('success', 'Demande transformée en partie et réponse envoyée.');
            return $this->redirectToRoute('app_manage_planning', ['id' => $event->getId()]);

        }

        // génération du formulaire

        // Récupérer la liste des événements visibles
        $events = $repository->findEventsToCome(false);
        if (!$events) {
            $this->addFlash('info', 'Aucun d\'événement n\'est plannifié pour le moment.');
            return $this->redirectToRoute('app_main');
        }

        return $this->render('manage/request/process.html.twig', [
            'partyRequest' => $partyRequest,
            'party' => $party,
            'event' => $partyRequest->getEvent(),
            'events' => $events,
            'form' => $form
        ]);
    }

    #[Route('/manage/request/{id}/refuse', name: 'app_manage_request_refuse', requirements: ['id' => Requirement::UUID_V7], methods: ['GET'])]
    public function requestRefuse(?partyRequest $partyRequest, EntityManagerInterface $manager, MailerInterface $mailer): Response
    {
        $user = $this->getUser();
        // la requête existe-t-elle bien ?
        if (!$partyRequest) {
            $this->addFlash('danger', 'Demande inconnue !');
            return $this->redirectToRoute('app_manage');
        }

        $event = $partyRequest->getEvent();
        $state = $partyRequest->getState();
        // La requête est-elle en attente d'une réponse ?
        if (!$state['code'] == "WAIT") {
            $this->addFlash('danger', 'Une réponse a déjà été apportée : '.$state['name'].'.');
            return $this->redirectToRoute('app_manage_planning', ['id' => $event->getId()]);
        }

        // On met à jour la demande
        $partyRequest->setModerator($user);
        $partyRequest->setModOnDate(new \Datetime('now'));
        $partyRequest->setAccepted(false);
        $manager->persist($partyRequest);

        // Et on sync dans la BDD
        $manager->flush();

        // On préviens par mail
        $email = (new TemplatedEmail())
            ->from(new Address($_ENV['CONTACT_EMAIL'], $_ENV['CONTACT_NAME']))
            ->to((string) $partyRequest->getRequester()->getEmail())
            ->subject('En réponse à votre demande pour '.$partyRequest->getEvent()->getName())
            ->htmlTemplate('manage/request/refused.email.html.twig')
            ->textTemplate('manage/request/refused.email.txt.twig')
            ->context([
                'partyRequest' => $partyRequest,
            ]);
        $mailer->send($email);

        $this->addFlash('success', 'Demande refusée et réponse envoyée.');
        return $this->redirectToRoute('app_manage_planning', ['id' => $event->getId()]);


    }
}
