<?php

namespace App\Controller;

use App\Entity\GlobalParameter;
use App\Entity\Prestataire;
use App\Entity\SolidoumeItem;
use App\Entity\SolidoumeParameter;
use App\Entity\TransactionAdherentPrestataire;
use App\Enum\CurrencyEnum;
use App\Enum\MoyenEnum;
use App\Form\Type\SolidoumeFormType;
use App\Utils\OperationUtils;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Core\Security;
use Twig\Environment;

class SolidoumeController extends AbstractController
{
    private $em;
    private $security;
    private $mailer;
    private $templating;
    private $operationUtils;

    public function __construct(EntityManagerInterface $em, Security $security, \Swift_Mailer $mailer, Environment $templating, OperationUtils $operationUtils)
    {
        $this->em = $em;
        $this->security = $security;
        $this->mailer = $mailer;
        $this->templating = $templating;
        $this->operationUtils = $operationUtils;
    }

    /**
     * @Route("/ssa/desinscription", name="solidoume_unsubscribe")
     */
    public function unsubscribeAction(Request $request)
    {
        if (!(null != $this->security->getUser()->getAdherent() && $this->security->getUser()->isGranted('ROLE_ADHERENT'))) {
            $this->addFlash(
                'error',
                'Page inaccessible, vous devez être connecté en adhérent !'
            );

            return $this->redirectToRoute('index');
        }
        $solidoumeItem = $this->em->getRepository(SolidoumeItem::class)->findOneBy(['adherent' => $this->security->getUser()->getAdherent(), 'enabled' => true]);
        $solidoumeItem->setEnabled(false);
        $this->em->persist($solidoumeItem);
        $this->em->flush();

        $solidoumeParam = $this->em->getRepository(SolidoumeParameter::class)->findTheOne();
        $name = 'la sécurite sociale alimentaire';
        if (null != $solidoumeParam) {
            $name = $solidoumeParam->getName();
        }
        $this->addFlash(
            'success',
            'Désinscription à ' . $name . ' bien prise en compte !'
        );

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

    /**
     * @Route("/ssa/adherer", name="solidoume_adherer")
     */
    public function adhererAction(Request $request)
    {
        if (!(null != $this->security->getUser()->getAdherent() && $this->security->getUser()->isGranted('ROLE_ADHERENT'))) {
            $this->addFlash(
                'error',
                'Page inaccessible, vous devez être connecté en adhérent !'
            );

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

        $solidoumeParam = $this->em->getRepository(SolidoumeParameter::class)->findTheOne();
        if (empty($solidoumeParam)) {
            $this->addFlash(
                'error',
                'Le programme de Sécurité Sociale Alimentaire non configuré !'
            );

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

        $data = $this->em->getRepository(SolidoumeItem::class)->findOneBy(['adherent' => $this->security->getUser()->getAdherent(), 'enabled' => true]);
        $alreadyExist = false;
        if (!empty($data)) {
            $alreadyExist = true;
        }
        $form = $this->createForm(SolidoumeFormType::class, $data);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $solidoumeItem = $form->getData();
            if (!$solidoumeItem->getIsRecurrent()) {
                if (!$this->takeMoneyFromSolidoume($solidoumeItem)) {
                    $referer = $request->headers->get('referer');

                    return $this->redirect($referer);
                } else {
                    $this->addFlash(
                        'success',
                        $solidoumeParam->getName() . ' : Merci de votre participation, celle-ci vient d\'être prélevée !'
                    );
                }
            } else {
                $this->addFlash(
                    'success',
                    $solidoumeParam->getName() . ' : Merci de votre participation, elle sera prélevée le ' . $solidoumeItem->getPaiementDate() . ' !'
                );
            }
            $this->em->persist($solidoumeItem);
            $this->em->flush();
            $this->sendMail($solidoumeItem);

            $referer = $request->request->get('referer');
            if ($referer && !$request->isXmlHttpRequest()) {
                return $this->redirect($referer);
            } elseif (!$request->isXmlHttpRequest()) {
                return new Response('', Response::HTTP_BAD_REQUEST);
            }
        }

        return $this->render('@kohinos/solidoume/index.html.twig', [
            'form' => $form->createView(),
            'param' => $solidoumeParam,
        ]);
    }

    private function takeMoneyFromSolidoume(SolidoumeItem $item)
    {
        $solidoumeParam = $this->em->getRepository(SolidoumeParameter::class)->findTheOne();
        $nowDay = (new \DateTime('now', new \DateTimeZone('UTC')))->format('d');
        $nowMonth = intval((new \DateTime('now', new \DateTimeZone('UTC')))->format('Ym'));
        $item->setPaiementDate($nowDay);
        $amount = $item->getAmount();
        $accountEmlc = $item->getAdherent()->getAccountWithCurrency(CurrencyEnum::CURRENCY_EMLC);
        if (null != $accountEmlc
            && $item->getPaiementDate() == $nowDay
            && $item->getLastMonthPayed() != $nowMonth) {
            if ($accountEmlc->getBalance() < $amount) {
                $this->addFlash(
                    'error',
                    $solidoumeParam->getName() . ' : Solde inférieur au montant à prélever ! (Solde : ' . $accountEmlc->getBalance() . ' eMLC) !'
                );

                return false;
            } else {
                $flux = new TransactionAdherentPrestataire();
                $flux->setExpediteur($item->getAdherent());
                $flux->setDestinataire($this->em->getRepository(Prestataire::class)->getPrestataireSolidoume());
                $flux->setMontant($amount);
                $flux->setMoyen(MoyenEnum::MOYEN_EMLC);
                $now = (new \Datetime('now'))->format('d/m/Y H:i:s');
                $flux->setReference($this->em->getRepository(SolidoumeParameter::class)->getValueOf('name') . ' prélèvement en date du ' . $now);
                $item->setLastMonthPayed($nowMonth);
                $item->setEnabled(false);
                $this->em->persist($flux);
                $this->em->persist($item);
                // Write operations for this flux !
                $this->operationUtils->executeOperations($flux);
                $this->em->flush();
            }
        }

        return true;
    }

    private function sendMail(SolidoumeItem $solidoumeItem)
    {
        $subject = $this->em->getRepository(SolidoumeParameter::class)->getValueOf('name');
        $from = $this->em->getRepository(GlobalParameter::class)->val(GlobalParameter::MLC_NOTIF_EMAIL);
        $mail = (new \Swift_Message($subject))
            ->setFrom($from)
            ->setTo($solidoumeItem->getUser()->getEmail())
            ->setBody(
                $this->templating->render(
                    '@kohinos/email/solidoume/confirm.html.twig',
                    [
                        'subject' => $subject,
                        'item' => $solidoumeItem,
                    ]
                ),
                'text/html'
            );
        $this->mailer->send($mail);
    }
}