<?php

namespace App\Controller;

use App\Entity\AchatMonnaie;
use App\Entity\AchatMonnaieAConfirmer;
use App\Entity\AchatMonnaieAConfirmerAdherent;
use App\Entity\AchatMonnaieAConfirmerPrestataire;
use App\Entity\AchatMonnaieAdherent;
use App\Entity\AchatMonnaiePrestataire;
use App\Entity\Adherent;
use App\Entity\Flux;
use App\Entity\HelloAsso;
use App\Entity\Prestataire;
use App\Entity\Reconversion;
use App\Enum\HelloassoStateEnum;
use App\Utils\CustomEntityManager;
use App\Utils\HelloassoUtils;
use App\Utils\OperationUtils;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\HttpFoundation\StreamedResponse;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Core\Security as SecurityS;

class AdminController extends Controller
{
    private $em;
    private $eventDispatcher;
    private $operationUtils;
    private $security;
    private $session;

    public function __construct(
        CustomEntityManager $em,
        SecurityS $security,
        EventDispatcherInterface $eventDispatcher,
        OperationUtils $operationUtils,
        HelloassoUtils $helloassoUtils,
        SessionInterface $session)
    {
        $this->em = $em;
        $this->eventDispatcher = $eventDispatcher;
        $this->security = $security;
        $this->operationUtils = $operationUtils;
        $this->helloassoUtils = $helloassoUtils;
        $this->session = $session;
    }

    /**
     * @Route("/admin/setenable/{type}/{id}", name="setenable")
     * @IsGranted("ROLE_ADMIN")
     */
    public function setEnableAction($type, $id, Request $request)
    {
        $referer = $request->headers->get('referer');
        if ($referer && !$request->isXmlHttpRequest()) {
            return $this->redirect($referer);
        } elseif (!$request->isXmlHttpRequest()) {
            return new Response('', Response::HTTP_BAD_REQUEST);
        }
        $status = 'success';
        try {
            $object = $this->em->getRepository(str_replace('.', ':', $type))->findOneById($id);
            if ($object && method_exists($object, 'setEnabled')) {
                $object->setEnabled(!$object->isEnabled());
                $this->em->persist($object);
                $this->em->flush();
            } else {
                $status = 'error';
                $this->session->getFlashBag()->add(
                    'notice',
                    'Erreur : veuillez recharger la page et réessayer !'
                );
            }
        } catch (\Exception $e) {
            $status = 'error';
            $this->session->getFlashBag()->add(
                'notice',
                'Erreur : veuillez recharger la page et réessayer !'
            );
        }

        return new JsonResponse(['status' => $status, 'newvalue' => ($object->isEnabled() ? 'true' : 'false')]);
    }

    /**
     * @Route("/admin/setreconverti/{id}", name="setreconverti")
     */
    public function setReconvertiAction(Reconversion $object, Request $request)
    {
        if ($this->security->isGranted('ROLE_SUPER_ADMIN') || $this->security->isGranted('ROLE_ADMIN_TRANSFERT_GERER_VIEW') || $this->security->isGranted('ROLE_ADMIN_RECONVERSION_GERER_ALL')) {
            $referer = $request->headers->get('referer');
            if ($referer && !$request->isXmlHttpRequest()) {
                return $this->redirect($referer);
            } elseif (!$request->isXmlHttpRequest()) {
                return new Response('', Response::HTTP_BAD_REQUEST);
            }
            $status = 'success';
            try {
                if ($object && method_exists($object, 'setReconverti')) {
                    $object->setReconverti(!$object->getReconverti());
                    $this->em->persist($object);
                    $this->em->flush();
                } else {
                    $status = 'error';
                }
            } catch (\Exception $e) {
                $status = 'error';
            }
        } else {
            $status = 'error';
        }

        return new JsonResponse(['status' => $status, 'newvalue' => ($object->getReconverti() ? 'true' : 'false')]);
    }

    /**
     * @Route("/validate/achat/monnaie/{id}", name="validate_achat_monnaie")
     * @Security("user.canValidateAchat == true and (is_granted('ROLE_SUPER_ADMIN') or is_granted('ROLE_ADMIN_SIEGE') or is_granted('ROLE_TRESORIER'))")
     */
    public function validateAchatMonnaieAction(Request $request, AchatMonnaieAConfirmer $achatAConfirmer)
    {
        $referer = $request->headers->get('referer');
        if ($referer && !$request->isXmlHttpRequest()) {
            return $this->redirect($referer);
        } elseif (!$request->isXmlHttpRequest()) {
            return new Response('', Response::HTTP_BAD_REQUEST);
        }
        $status = 'success';
        try {
            $flux = new AchatMonnaie();
            if ($achatAConfirmer instanceof AchatMonnaieAConfirmerAdherent) {
                $flux = new AchatMonnaieAdherent();
            } elseif ($achatAConfirmer instanceof AchatMonnaieAConfirmerPrestataire) {
                $flux = new AchatMonnaiePrestataire();
            }
            $flux->setOperateur($this->getUser());
            $flux->setRole($this->getUser()->getGroups()[0]->__toString());
            $flux->setExpediteur($achatAConfirmer->getExpediteur());
            $flux->setDestinataire($achatAConfirmer->getDestinataire());
            $flux->setMontant($achatAConfirmer->getMontant());
            $flux->setMoyen($achatAConfirmer->getMoyen());
            $flux->setReference($achatAConfirmer->getReference());
            $flux->setReconverti(true);
            $flux->setData(['validationAchat' => true]);
            $achatAConfirmer->setReconverti(true);
            $this->em->persist($achatAConfirmer);
            $this->em->flush();

            // Write operations for this flux !
            $this->operationUtils->executeOperations($flux);
        } catch (\Exception $e) {
            // TMP
            // throw $e;
            $status = "Error : {$e->getMessage()}";
        }

        return new JsonResponse(['status' => $status]);
    }

    /**
     * @Route("/helloasso/associate/{id}", name="helloasso_associate")
     * @Security("(is_granted('ROLE_SUPER_ADMIN') or is_granted('ROLE_ADMIN_SIEGE') or is_granted('ROLE_TRESORIER'))")
     */
    public function helloassoAssociateAction(Request $request, $id)
    {
        if ($this->em->getFilters()->isEnabled('enabled_filter')) {
            $this->em->getFilters()->disable('enabled_filter');
        }
        $helloasso = $this->em->getRepository(HelloAsso::class)->findOneById($id);

        $status = 'success';
        $flashMessage = 'Transaction HelloAsso correctement associée ';

        if (null != $request->get('presta') && null != $request->get('adherent')) {
            $status = 'Erreur : il faut choisir un adherent OU un prestataire !';

            return new JsonResponse(['status' => false, 'error' => $status]);
        } elseif (null != $request->get('presta')) {
            $prestataire = $this->em->getRepository(Prestataire::class)->findOneById($request->get('presta'));
            $helloasso->setPrestataire($prestataire);
            $flashMessage .= 'au prestataire ' . $prestataire->__toString();
        } elseif (null != $request->get('adherent')) {
            $adherent = $this->em->getRepository(Adherent::class)->findOneById($request->get('adherent'));
            $helloasso->setAdherent($adherent);
            $flashMessage .= 'à l\'adherent ' . $adherent->__toString();
        }
        if ('Membership' == $helloasso->getType()) {
            // COTISATION
            $flux = $this->helloassoUtils->addCotisation($helloasso);
            $helloasso->setFlux($flux);
        } elseif ('Payment' == $helloasso->getType()) {
            // ACHAT EMLC
            $flux = $this->helloassoUtils->addAchatEmlc($helloasso);
            $helloasso->setFlux($flux);
        } elseif ('Donation' == $helloasso->getType()) {
            // DONATION
            $flux = $this->helloassoUtils->addDonation($helloasso);
            $helloasso->setFlux($flux);
        }
        $helloasso->setErrors(null);
        $helloasso->setOperationState(HelloassoStateEnum::HELLOASSO_STATE_OK);
        $this->em->persist($helloasso);
        $this->em->flush();

        $this->session->getFlashBag()->add(
            'success',
            $flashMessage
        );
        if (!$this->em->getFilters()->isEnabled('enabled_filter')) {
            $this->em->getFilters()->enable('enabled_filter');
        }

        return new JsonResponse(['status' => $status]);
    }

    /**
     * @Route("/admin/getcsv", name="getcsv")
     * @IsGranted({"ROLE_SUPER_ADMIN", "ROLE_ADMIN_IMPORT_EDIT", "ROLE_ADMIN_IMPORT_LIST", "ROLE_ADMIN_IMPORT_CREATE", "ROLE_ADMIN_IMPORT_VIEW", "ROLE_ADMIN_IMPORT_DELETE", "ROLE_ADMIN_IMPORT_EXPORT", "ROLE_ADMIN_IMPORT_ALL"})
     */
    public function getCsvAction(Request $request)
    {
        $data = $request->get('data');
        $header = $request->get('header');
        $response = new StreamedResponse();
        $response->setCallback(function () use ($data, $header) {
            $handle = fopen('php://output', 'w+');
            // Nom des colonnes du CSV
            fputcsv($handle, explode(';', $header), ';');

            //Champs
            foreach ($data as $row) {
                // fwrite($handle, $row);
                fputcsv($handle, explode(';', $row), ';');
            }
            fclose($handle);
        });
        $response->setStatusCode(200);
        $response->headers->set('Content-Type', 'text/csv; charset=utf-8');
        $response->headers->set('Content-Disposition', 'attachment; filename="export.csv"');

        return $response;
    }
}
