<?php

namespace App\Controller;

use App\Entity\AchatMonnaieAConfirmerAdherent;
use App\Entity\AchatMonnaieAdherent;
use App\Entity\Adherent;
use App\Entity\GlobalParameter;
use App\Entity\Payment;
use App\Entity\TransactionAdherentAdherent;
use App\Entity\TransactionAdherentPrestataire;
use App\Form\Type\AchatMonnaieAConfirmerAdherentFormType;
use App\Form\Type\AchatMonnaieAdherentFormType;
use App\Form\Type\AchatMonnaieAdherentRecurrentFormType;
use App\Form\Type\AdherentInfosFormType;
use App\Form\Type\TransactionAdherentAdherentFormType;
use App\Form\Type\TransactionAdherentPrestataireFormType;
use App\Form\Type\SetPaymentCodeFormType;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;

class UserAdherentController extends FluxController
{
    /**
     * @Route("/adherent/infos", name="adherent_infos")
     * @IsGranted("ROLE_ADHERENT")
     */
    public function adherentInfosAction(Request $request)
    {
        $form = $this->createForm(AdherentInfosFormType::class, $this->getUser()->getAdherent());
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $this->em->persist($form->getData());
            $this->em->flush();
            $this->addFlash(
                'success',
                $this->translator->trans('Infos de l\'adhérent modifiées !')
            );
            $referer = $request->headers->get('referer');
            if ($referer && !$request->isXmlHttpRequest()) {
                return $this->redirect($referer);
            } elseif (!$request->isXmlHttpRequest()) {
                return new Response('', Response::HTTP_BAD_REQUEST);
            }
        }

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

    /**
     * @Route("/adherent/transaction/prestataire/", name="transactionAdherentPrestataire")
     * @IsGranted("ROLE_ADHERENT")
     */
    public function transactionAdherentPrestataireAction(Request $request)
    {
        $entity = new TransactionAdherentPrestataire();
        $entity->setOperateur($this->getUser());
        $entity->setExpediteur($this->getUser()->getAdherent());
        $form = $this->createForm(TransactionAdherentPrestataireFormType::class, $entity);

        return $this->manageFluxForm(
            $request,
            $form
        );
    }

    /**
     * @Route("/adherent/transaction/adherent/", name="transactionAdherentAdherent")
     * @IsGranted("ROLE_ADHERENT")
     */
    public function transactionAdherentAdherentAction(Request $request)
    {
        if (empty($this->getUser()) || empty($this->getUser()->getAdherent())) {
            return $this->redirectToRoute('index');
        }
        $entity = new TransactionAdherentAdherent();
        $entity->setOperateur($this->getUser());
        $entity->setExpediteur($this->getUser()->getAdherent());
        $form = $this->createForm(TransactionAdherentAdherentFormType::class, $entity);

        return $this->manageFluxForm(
            $request,
            $form
        );
    }

    /**
     * @Route("/adherent/achat-monnaie/", name="achatMonnaieAdherent")
     * @IsGranted("ROLE_ADHERENT")
     */
    public function achatMonnaieAdherentAction(Request $request)
    {
        if (empty($this->getUser()) || empty($this->getUser()->getAdherent())) {
            return $this->redirectToRoute('index');
        }

        $entity = new AchatMonnaieAdherent();
        $form = $this->createForm(AchatMonnaieAdherentFormType::class, $entity);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            if ($form->has('payOther') && $form->get('payOther')->isClicked()) {
                return $this->redirectToRoute('achatMonnaieAConfirmerAdherent');
            } elseif ($form->has('save') && $form->get('save')->isClicked()) {
                return $this->forward('App\Controller\PaymentController::preparePaymentAction', [
                    'form'  => $form,
                    'type'  => Payment::TYPE_ACHAT_MONNAIE_ADHERENT
                ]);
            } elseif ($form->has('saveHelloAsso') && $form->get('saveHelloAsso')->isClicked()) {
                $url = $this->em->getRepository(GlobalParameter::class)->val(GlobalParameter::HELLOASSO_URL_EMLC_ADHERENT);

                return $this->redirect($url);
            }
        }

        return $this->render('@kohinos/flux/transaction.html.twig', [
            'form' => $form->createView(),
            'title' => $this->translator->trans('Achat de monnaie locale'),
        ]);
    }

    /**
     * Validations before proceeding to payment.
     * 
     * Returns error message or null if no error.
     */
    private function paiementCotisTavValidation($flux) {

        $destinataire = $flux->getDestinataire();
        if($reason = $this->tavCotisationUtils->preventCotisationDuplication($destinataire)) {
            return $reason;
        }

        // Look for cotisation data depending on active process
        if (true == $this->getParameter('simplified_household_based_allowance')) {
            $cotisationAmount = $destinataire->getCotisationAmount();

            // Use ProfilDeCotisation if set & conditions for simplified_household_based_allowance not met
            if ((is_null($cotisationAmount) || is_null($destinataire->getHouseholdCount())) && is_null($destinataire->getProfilDeCotisation())) {
                return "Opération impossible : votre profil est incomplet, informations de cotisation manquantes. Veuillez contacter un administrateur.";
            }
        } else if (true == $this->getParameter('household_based_allowance')) {
            $cotisationAmount = $destinataire->getCotisationAmount();

            if (is_null($cotisationAmount) || is_null($destinataire->getHouseholdAdultCount())) {
                return "Opération impossible : votre profil est incomplet, informations de cotisation manquantes. Veuillez contacter un administrateur.";
            }
        } else {
            $profile = $destinataire->getProfilDeCotisation();

            if (is_null($profile)) {
                return "Opération impossible : vous n'avez pas de profil de cotisation associé. Veuillez contacter un administrateur.";
            }
        }

        return null;
    }
    
    /**
     * @Route("/adherent/paiement-cotis-tav/", name="paiementCotisTav")
     * @IsGranted("ROLE_ADHERENT")
     */
    public function paiementCotisTavAction(Request $request)
    {
        if (empty($this->getUser()) || empty($this->getUser()->getAdherent())) {
            return $this->redirectToRoute('index');
        }

        $entity = new AchatMonnaieAdherent();
        $form = $this->createForm(AchatMonnaieAdherentFormType::class, $entity);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $flux = $form->getData();

            $validationError = $this->paiementCotisTavValidation($flux);
            if (!is_null($validationError)) {
                $this->addFlash(
                    'error',
                    $this->translator->trans($validationError)
                );

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

            if (null == $flux->getDon() || 0 == $flux->getDon()->getMontant()) {
                $flux->setDon(null);
            }

            // Redirect to payment
            return $this->forward('App\Controller\PaymentController::preparePaymentAction', [
                'form'  => $form,
                'type'  => Payment::TYPE_PAIEMENT_COTISATION_TAV
            ]);

            /* For test purposes, comment redirection above and uncomment following part to skip payment */
            // $this->em->persist($flux);
            // $this->operationUtils->executeOperations($flux);

            // // Apply cotisation rate, create new flux
            // $destinataire = $flux->getDestinataire();
            // $allocationMethod = $this->tavCotisationUtils->getAppropriateAllocationMethod($destinataire);
            
            // // Create new flux for cotisation, depending on process
            // if ($this->getParameter('household_based_allowance') || $this->getParameter('simplified_household_based_allowance')) {
            //     $this->tavCotisationUtils->applyHouseholdAllowance($flux);
            // } else {
            //     $this->tavCotisationUtils->applyTauxCotisation($flux);
            // }
            
            // $this->em->flush();
            // $this->addFlash(
            //     'success',
            //     $this->translator->trans('Cotisation payée ! [Paiement via Payzen temporairement désactivé]')
            // );

            // return $this->redirectToRoute('index');
        }

        return $this->render('@kohinos/flux/transaction.html.twig', [
            'form' => $form->createView(),
            'title' => $this->translator->trans('Payer sa cotisation'),
        ]);
    }

    /**
     * @Route("/adherent/paiement-reccurent-cotis-tav/", name="paiementRecurrentCotisTav")
     * @IsGranted("ROLE_ADHERENT")
     */
    public function paiementRecurrentCotisTavAction(Request $request)
    {
        if (empty($this->getUser()) || empty($this->getUser()->getAdherent())) {
            return $this->redirectToRoute('index');
        }

        $entity = new AchatMonnaieAdherent();
        $form = $this->createForm(AchatMonnaieAdherentRecurrentFormType::class, $entity);
        $form->handleRequest($request);

        if (!$form->isValid()) {
            foreach($form->getErrors(true) as $error) {
                $this->addFlash('error', $error->getMessage());
            }
            return $this->redirectToRoute('index');
        }

        if ($form->isSubmitted() && $form->isValid()) {
            $flux = $form->getData();

            $validationError = $this->paiementCotisTavValidation($flux);
            if (!is_null($validationError)) {
                $this->addFlash(
                    'error',
                    $this->translator->trans($validationError)
                );

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

            if (null == $flux->getDon() || 0 == $flux->getDon()->getMontant()) {
                $flux->setDon(null);
            }

            // Redirect to payment
            return $this->forward('App\Controller\PaymentController::preparePaymentAction', [
                'form'  => $form,
                'type'  => Payment::TYPE_PAIEMENT_RECURRENT_COTISATION_TAV
            ]);
        }

        return $this->render('@kohinos/flux/transaction.html.twig', [
            'form' => $form->createView(),
            'title' => $this->translator->trans('Payer sa cotisation'),
        ]);
    }

    /**
     * @Route("/adherent/demande/achat-monnaie/", name="achatMonnaieAConfirmerAdherent")
     * @IsGranted("ROLE_ADHERENT")
     */
    public function achatMonnaieAConfirmerAdherentAction(Request $request)
    {
        if (empty($this->getUser()) || empty($this->getUser()->getAdherent())) {
            return $this->redirectToRoute('index');
        }
        $entity = new AchatMonnaieAConfirmerAdherent();
        $form = $this->createForm(AchatMonnaieAConfirmerAdherentFormType::class, $entity);

        return $this->manageFluxForm(
            $request,
            $form,
            '@kohinos/flux/demande_achat_monnaie.html.twig',
            ['title' => $this->translator->trans("Demande d'achat de monnaie locale numérique")]
        );
    }

    /**
     * @Route("/adherent/liste/demande/achat-monnaie/", name="listachatMonnaieAConfirmerAdherent")
     * @IsGranted("ROLE_ADHERENT")
     */
    public function listachatMonnaieAConfirmerAdherentAction(Request $request)
    {
        if (empty($this->getUser()) || empty($this->getUser()->getAdherent())) {
            return $this->redirectToRoute('index');
        }

        $q = $this->em->getRepository(AchatMonnaieAConfirmerAdherent::class)->findBy(['destinataire' => $this->getUser()->getAdherent()], ['createdAt' => 'DESC']);

        return $this->render('@kohinos/flux/list_demande_achat_monnaie.html.twig', [
            'datas' => $q,
        ]);
    }

    /**
     * @Route("/adherent/set-payment-code", name="adherentSetPaymentCode")
     * @IsGranted("ROLE_ADHERENT")
     */
    public function setPaymentCodeAction(Request $request)
    {
        $adherent = $this->getUser()->getAdherent();
        $form = $this->createForm(SetPaymentCodeFormType::class, $adherent);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $data = $form->getData();
            $plainCode = $data->getPaymentCode();

            if (ctype_digit($plainCode) && strlen($plainCode) >= 4 && strlen($plainCode) <= 8) {
                $encoded = crypt($plainCode, $this->getUser()->getSalt());

                $adherent->setPaymentCode($encoded);
    
                $this->em->flush();
                $this->addFlash(
                    'success',
                    $this->translator->trans('Code de paiement modifié !')
                );
            } else {
                $this->addFlash(
                    'error',
                    $this->translator->trans('Le code de paiement doit être composé de 4 à 8 chiffres.')
                );
            }
        }

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