<?php
/**
 * @author Colinet Julien
 */

namespace CpCreation\VitiCore\Bridge\Symfony\Bundle\Controller\Site;

use CpCreation\VitiCore\Bridge\Symfony\Bundle\Form\Admin\GiftCheckType;
use CpCreation\VitiCore\Bridge\Symfony\Bundle\Form\Site\CartType;
use CpCreation\VitiCore\Bridge\Symfony\Bundle\Form\Site\CheckCodePriceType;
use CpCreation\VitiCore\Bridge\Symfony\Bundle\Payment\AxeptaPayment;
use CpCreation\VitiCore\Bridge\Symfony\Bundle\Payment\MoneticoPayment;
use CpCreation\VitiCore\Bridge\Symfony\Bundle\Payment\PayPlugPayment;
use CpCreation\VitiCore\Bridge\Symfony\Bundle\Payment\Sherlock2Payment;
use CpCreation\VitiCore\Bridge\Symfony\Bundle\Payment\SherlockPayment;
use CpCreation\VitiCore\Bridge\Symfony\Bundle\Payment\SogeCommercePayment;
use CpCreation\VitiCore\Bridge\Symfony\Bundle\Payment\SystemPayPayment;
use CpCreation\VitiCore\Bridge\Symfony\Bundle\Service\SherlockService;
use CpCreation\VitiCore\Bridge\Symfony\Bundle\Utils\CalculDegressive;
use CpCreation\VitiCore\Bridge\Symfony\Bundle\Utils\CalculShipping;
use CpCreation\VitiCore\Bridge\Symfony\Bundle\Utils\Mailer;
use CpCreation\VitiCore\Cart\Model\Cart;
use CpCreation\VitiCore\Cart\Model\Promo;
use CpCreation\VitiCore\Cart\Repository\CartRepository;
use CpCreation\VitiCore\Cart\Repository\PromoRepository;
use CpCreation\VitiCore\Contact\Repository\ContactRepository;
use CpCreation\VitiCore\Payment\Model\Payment;
use CpCreation\VitiCore\Payment\Repository\PaymentRepository;
use CpCreation\VitiCore\Product\Model\Product;
use CpCreation\VitiCore\Product\Model\ProductGift;
use CpCreation\VitiCore\Product\Repository\ProductGiftRepository;
use CpCreation\VitiCore\Product\Repository\ProductPriceCodeRepository;
use CpCreation\VitiCore\Product\Repository\ProductPriceGroupRepository;
use CpCreation\VitiCore\Shop\Model\ShippingCountry;
use CpCreation\VitiCore\Shop\Repository\ShippingCountryRepository;
use CpCreation\VitiCore\Shop\Repository\ShippingCountyRepository;
use CpCreation\VitiCore\Shop\Repository\ShippingZoneRepository;
use CpCreation\VitiCore\Shop\Repository\ShopConfigRepository;
use Doctrine\ORM\EntityManagerInterface;
use Exception;
use League\Glide\Api\Api;
use Payplug\Payplug;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\Routing\Annotation\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
use Payplug\Resource;
use Payplug\Resource\APIResource;
use CpCreation\VitiCore\Bridge\Symfony\Bundle\Payment\CawlPayment;

class CartController extends AbstractController
{
    private $calculShipping;
    private $calculDegressive;
    private $promoRepository;
    private $productPriceCodeRepository;
    private $productPriceGroupRepository;
    private $cartRepository;
    private $paymentRepository;
    private $contactRepository;
    private $router;
    private $translator;
    private $mailer;
    private $moneticoPayment;
    private $sherlockPayment;
    private $shippingCountryRepository;
    private $shippingCountyRepository;
    private $shippingZoneRepository;
    private $em;
    private $sherlockFinder;
    private $sherlock_dir;
    private $systempayPayment;
    private $sogeCommercePayment;
    private $axeptaPayment;
    private $sherlock2Payment;
    private $session;
    private $giftRepository;
    private $shopConfigRepository;
    private $payplugPayment;
    private $cawlPayment;

    public function __construct(CalculShipping $calculShipping,
        CalculDegressive $calculDegressive,
        PromoRepository $promoRepository,
        ProductPriceCodeRepository $productPriceCodeRepository,
        ProductPriceGroupRepository $productPriceGroupRepository,
        ShippingCountryRepository $shippingCountryRepository,
        ShippingCountyRepository $shippingCountyRepository,
        ShippingZoneRepository $shippingZoneRepository,
        CartRepository $cartRepository,
        PaymentRepository $paymentRepository,
        ContactRepository $contactRepository,
        RouterInterface $router,
        TranslatorInterface $translator,
        Mailer $mailer,
        MoneticoPayment $moneticoPayment,
        SherlockPayment $sherlockPayment,
        SherlockService $sherlockService,
        $sherlockDir,
        SystemPayPayment $systemPayPayment,
        SogeCommercePayment $sogeCommercePayment,
        AxeptaPayment $axeptaPayment,
        Sherlock2Payment $sherlock2Payment,
        PayPlugPayment $payPlugPayment,
        EntityManagerInterface $em,
        SessionInterface $session,
        ProductGiftRepository $giftRepository,
        ShopConfigRepository $shopConfigRepository,
        CawlPayment $cawlPayment
    ) {
        $this->calculShipping              = $calculShipping;
        $this->calculDegressive            = $calculDegressive;
        $this->promoRepository             = $promoRepository;
        $this->productPriceCodeRepository  = $productPriceCodeRepository;
        $this->productPriceGroupRepository = $productPriceGroupRepository;
        $this->shippingCountryRepository   = $shippingCountryRepository;
        $this->shippingCountyRepository    = $shippingCountyRepository;
        $this->shippingZoneRepository      = $shippingZoneRepository;
        $this->cartRepository              = $cartRepository;
        $this->paymentRepository           = $paymentRepository;
        $this->contactRepository           = $contactRepository;
        $this->router                      = $router;
        $this->translator                  = $translator;
        $this->mailer                      = $mailer;
        $this->moneticoPayment             = $moneticoPayment;
        $this->em                          = $em;
        $this->sherlockPayment             = $sherlockPayment;
        $this->sherlockFinder              = $sherlockService;
        $this->sherlock_dir                = $sherlockDir;
        $this->systempayPayment            = $systemPayPayment;
        $this->sogeCommercePayment         = $sogeCommercePayment;
        $this->axeptaPayment               = $axeptaPayment;
        $this->sherlock2Payment            = $sherlock2Payment;
        $this->session                     = $session;
        $this->giftRepository              = $giftRepository;
        $this->shopConfigRepository        = $shopConfigRepository;
        $this->payplugPayment              = $payPlugPayment;
        $this->cawlPayment                 = $cawlPayment;

    }

    /**
     * @param Request $request
     * @Route("/request/calcul_shipping", options={"expose"=true}, name="calcul_shipping")
     *
     * @return JsonResponse
     */
    public
    function shippingCalculAction(Request $request
    ) {
        $form = $this->createForm(CartType::class);
        $form->handleRequest($request);
        /**
         * @var Cart $cart
         */
        $cart = $form->getData();
        try {
            $shipping = $this->calculShipping->shippingTotalPrice($cart);

            return new JsonResponse($shipping['amount'], 200);
        } catch (\Exception $e) {

            return new JsonResponse($e->getMessage(), 400);
        }
    }

    /**
     * @param Request $request
     *
     * @Route("/request/promo_code", options={"expose"=true}, name="promo_code")
     *
     * @return JsonResponse
     * @throws \Doctrine\ORM\NonUniqueResultException
     */
    public
    function CodePromoAction(Request $request
    ) {

        $locale = $request->getLocale();
        $form   = $this->createForm(CartType::class);
        $form->handleRequest($request);
        /** @var Cart $cart */
        $cart         = $form->getData();
        $withShipping = false;
        /** @var Promo $promo */
        $promo = $this->promoRepository->findPromoActivWithCode($cart, $this->session->get('groupPrice', null));
        $gift  = $this->giftRepository->findGiftFromCart($cart);
        if ($promo) {
            if ($promo->getZones()->count() > 0) {
                if (!$cart->getInvoiceAddress()->getPostalCode() || !$cart->getInvoiceAddress()->getCountry()) {
                    return new JsonResponse(
                        [
                            'value'       => null,
                            'valueAmount' => null,
                            'message'     => $this->translator->trans('shop.promo_code.empty_zone', [], null, $locale),
                        ], 400
                    );
                }
                /** @var ShippingCountry $country */
                $country = $this->shippingCountryRepository->findOneByGroup($cart->getDeliveryAddress()->getCountry(), $this->session->get('groupPrice', null));
                $county  = null;
                if ($country->isCounty()) {
                    $department = substr($cart->getDeliveryAddress()->getPostalCode(), 0, 2);
                    $county     = $this->shippingCountyRepository->findDepartmentByCountry($department, $country->getCode());
                }
                $zone  = $this->shippingZoneRepository->findByCountryAndByCounty($country, $county);
                $promo = $this->promoRepository->findPromoActivWithCode($cart, $this->session->get('groupPrice', null), $zone);
            }
            if ($promo) {
                $amount  = 0;
                $percent = 0;
                if (!$promo->getMaxCount() || (($promo->getCount() < $promo->getMaxCount()))) {
                    if ($promo->getProducts()->count() > 0) {
                        $errorProducts = '';
                        /** @var Product $product */
                        $quantity = $cart->getQuantityByProducts($promo->getProducts());
                        foreach ($promo->getProducts() as $key => $product) {
                            if ($key === 0) {
                                $errorProducts .= $product->getName().' '.$product->getQuality();
                            } else {
                                $errorProducts .= ' ou '.$product->getName().' '.$product->getQuality();
                            }

                            $productCount = 1;
                        }

                    } else {
                        $quantity      = $cart->getQuantityAllAbsolute();
                        $errorProducts = null;
                        $productCount  = 0;
                    }
                    if (($promo->getMinEquivalency() && $quantity < $promo->getMinEquivalency()) || ($promo->getMaxEquivalency() && $quantity > $promo->getMaxEquivalency())) {
                        if ($quantity < $promo->getMinEquivalency()) {
                            $message = 'shop.promo_code.qty_error_min';
                            $qty     = $promo->getMinEquivalency();
                        } else {
                            $message = 'shop.promo_code.qty_error_max';
                            $qty     = $promo->getMaxEquivalency();
                        }

                        return new JsonResponse(
                            [
                                'valuePercent' => null,
                                'valueAmount'  => null,
                                'message'      => $this->translator->trans(
                                    $message, [
                                    '%count%'    => $productCount,
                                    '%qty%'      => $qty,
                                    '%products%' => $errorProducts,
                                ], null, $locale
                                ),
                            ], 400
                        );
                    }
                    if ($promo->getPercent()) {
                        $percent = $promo->getPercent();
                        if ($promo->isIncludeShippingFees()) {
                            $withShipping = true;
                        }
                    }
                    if ($promo->getPercent() && $promo->isIncludeShippingFees()) {
                        $withShipping = true;
                    }
                    if ($promo->getPercentShippingCost()) {
                        $shippingCost = $this->calculShipping->shippingTotalPrice($cart);
                        //$promoAmount  = ceil($shippingCost['amount'] * $promo->getPercentShippingCost());
                        $amount = $amount + round($shippingCost['amount'] * $promo->getPercentShippingCost());
                    }
                    if ($promo->isMultipleByQuantity()) {
                        $amount = $amount + $promo->getAmount() * floor($quantity / $promo->getMinEquivalency());
                    } else {
                        $amount = $amount + $promo->getAmount();
                    }
                    if ($percent === 0) {
                        $percent = null;
                    }
                    if ($amount === 0) {
                        $amount = null;
                    }

                    return new JsonResponse(
                        [
                            'valuePercent' => $percent,
                            'valueAmount'  => $amount,
                            'withShipping' => $withShipping,
                            'message'      => $this->translator->trans('shop.promo_code.success', [], null, $locale),
                        ], 200
                    );
                } else {
                    return new JsonResponse(
                        [
                            'valuePercent' => null,
                            'valueAmount'  => null,
                            'withShipping' => $withShipping,
                            'message'      => $this->translator->trans('shop.promo_code.count_error', [], null, $locale),
                        ], 400
                    );
                }
            } else {
                return new JsonResponse(
                    [
                        'valuePercent' => null,
                        'valueAmount'  => null,
                        'withShipping' => $withShipping,
                        'message'      => $this->translator->trans('shop.promo_code.error_zone', [], null, $locale),
                    ], 400
                );
            }
        } elseif ($gift) {
            return new JsonResponse(
                [
                    'valuePercent' => null,
                    'valueAmount'  => $gift->getCartItem()->getPrice(),
                    'message'      => $this->translator->trans('shop.promo_code.gift_success', [], null, $locale),
                ], 200
            );
        } else {
            return new JsonResponse(
                [
                    'valuePErcent' => null,
                    'valueAmount'  => null,
                    'withShipping' => $withShipping,
                    'message'      => $this->translator->trans('shop.promo_code.error', [], null, $locale),
                ], 400
            );
        }
    }

    /**
     * @param Request $request
     * @Route("/request/promo_code_auto", options={"expose"=true}, name="promo_code_auto")
     */
    public
    function CodePromoAutoAction(Request $request
    ) {
        $locale = $request->getLocale();
        $form   = $this->createForm(CartType::class);
        $form->handleRequest($request);
        /** @var Cart $cart */
        $cart = $form->getData();

        if ($cart->getInvoiceAddress()->getEmail() && $cart->getInvoiceAddress()->getPhone() && $cart->getInvoiceAddress()->getPostalCode() && $cart->getInvoiceAddress()->getCountry()) {

            /** @var ShippingCountry $country */
            $country = $this->shippingCountryRepository->findOneByGroup($cart->getDeliveryAddress()->getCountry(), $this->session->get('groupPrice', null));
            $county  = null;
            if ($country->isCounty()) {
                $department = substr($cart->getDeliveryAddress()->getPostalCode(), 0, 2);
                $county     = $this->shippingCountyRepository->findDepartmentByCountry($department, $country->getCode());
            }
            $zone = $this->shippingZoneRepository->findByCountryAndByCounty($country, $county);
            /** @var Promo $promo */
            $promo = $this->promoRepository->findPromoActivAutoWithGroup($cart, $this->session->get('groupPrice', null), $zone);

            if ($promo && (!$promo->getMaxCount() || ($promo->getCount() < $promo->getMaxCount()))) {

                if ($promo->getProducts()->count() > 0) {
                    $quantity = $cart->getQuantityByProducts($promo->getProducts());
                } else {
                    $quantity = $cart->getQuantityAllAbsolute();
                }

                $countByUser = $this->cartRepository->countPromoByUser($promo, $cart);
                if (!$promo->getMaxCountByCustomer() || ($promo->getMaxCountByCustomer() > count($countByUser))) {

                    if ($promo->getPercentShippingCost()) {
                        $shippingCost = $this->calculShipping->shippingTotalPrice($cart);
                        $promoAmount  = ceil($shippingCost['amount'] * $promo->getPercentShippingCost());
                    } else {
                        if ($promo->isMultipleByQuantity()) {
                            $promoAmount = $promo->getAmount() * floor($quantity / $promo->getMinEquivalency());
                        } else {
                            $promoAmount = $promo->getAmount();
                        }
                    }

                    return new JsonResponse(
                        [
                            'valuePercent' => $promo->getPercent(),
                            'valueAmount'  => $promoAmount,
                            'message'      => $this->translator->trans('shop.promo_code.success', [], null, $locale),
                        ], 200
                    );
                } else {
                    return new JsonResponse(
                        [
                            'value'       => null,
                            'valueAmount' => null,
                            'message'     => $this->translator->trans('shop.promo_code.count_error', [], null, $locale),
                        ], 400
                    );
                }
            }
        }

        return new JsonResponse(
            [
                'value'       => null,
                'valueAmount' => null,
                'message'     => $this->translator->trans('shop.promo_code.error', [], null, $locale),
            ], 400
        );
    }

    /**
     * @param Request $request
     *
     * @Route("/request/price_promo", options={"expose"=true}, name="promo_price")
     *
     * @return JsonResponse
     * @throws \Doctrine\ORM\NonUniqueResultException
     * @throws \Exception
     */
    public
    function PricePromoAction(Request $request
    ) {
        $form = $this->createForm(CartType::class);
        $form->handleRequest($request);
        $cart       = $form->getData();
        $degressive = $this->calculDegressive->calcul($cart);

        if ($degressive) {
            return new JsonResponse($degressive, 200);
        }

        return new JsonResponse(null, 400);
    }

    /**
     * @Template("@CpCreationVitiCore/site/_formCodePrice.html.twig")
     * @Route(path="/request/check-code-price", name="price_code")
     * @param Request $request
     *
     * @return array|\Symfony\Component\HttpFoundation\RedirectResponse
     */
    public
    function codePriceGroupAction(Request $request
    ) {
        $locale = $request->getLocale();
        $form   = $this->createForm(CheckCodePriceType::class);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $data   = $form->getData();
            $code   = str_replace(' ', '', $data['code']);
            $result = $this->productPriceCodeRepository->findOneCode($code);
            if ($result) {
                $response = new RedirectResponse($this->router->generate('shop', ['_locale' => $locale]));
                $this->session->set("groupPrice", $result->getGroup()->getId()->toString());
                $this->session->set("groupByDefault", false);
                $this->session->set("codePrice", $result->getId()->toString());
                //$response->headers->setCookie(new Cookie('PRICE', $result->getId(), time() + (1 * 24 * 60 * 60), '/', null, false, false));
                $this->addFlash(
                    'success', $this->translator->trans(
                    'shop.form.partner.success', [
                    '%code%' => $code,
                ], null, $locale
                )
                );

                return $response;
            }

            $this->addFlash(
                'error', $this->translator->trans(
                'shop.form.partner.error_exist', [
                '%code%' => $code,
            ], null, $locale
            )
            );

            return $this->redirectToRoute('shop', ['_locale' => $locale]);
        }

        return [
            'form' => $form->createView(),
        ];
    }

    /**
     * @Route(path="/request/check-code-price/delete", name="price_code_delete")
     *
     * @return array|\Symfony\Component\HttpFoundation\RedirectResponse
     */
    public
    function deleteCodePriceGroupAction(Request $request
    ) {
        $locale   = $request->getLocale();
        $response = new RedirectResponse($this->router->generate('shop', ['_locale' => $locale]));
        $this->get('session')->set('cart', null);
        $this->session->set("groupPrice", null);
        $this->session->set("groupByDefault", true);
        $this->session->set("codePrice", null);

        return $response;
    }

    /**
     * @param Request $request
     * @Route("/request/etransactions/responseAt", name="etransactions_responseAt")
     *
     * @return Response
     * @throws \Doctrine\ORM\NonUniqueResultException
     * @throws \Twig\Error\LoaderError
     * @throws \Twig\Error\RuntimeError
     * @throws \Twig\Error\SyntaxError
     */
    public
    function EtransactionsResponseAt(Request $request
    ) {

        if ($request->request->get('Erreur')) {

            $code = $request->request->get('Erreur', null);

        } else {
            $code = $request->query->get('Erreur', null);
        }

        if ($request->request->get('Ref')) {

            $ref = $request->request->get('Ref', null);

        } else {
            $ref = $request->query->get('Ref', null);
        }

        if ($request->request->all()) {

            $response = $request->request->all();

        } else {
            $response = $request->query->all();
        }
        if (!$ref || !$code) {
            throw new BadRequestHttpException();
        }
        /** Accès au variant désactivé, si paiement effectué après la désactivation d'un variant  */
        $this->em->getFilters()->disable("soft_deletable");
        /** @var Cart $cart */
        $cart = $this->cartRepository->findOneBy(['token' => $ref]);
        if ($cart) {
            $checkout = $cart->getCartCheckout();
            $checkout->setResponse($response);
            if ($code === '00000') {
                $checkout->setPayedAt(new \DateTime('now'));
                $this->getDoctrine()->getManager()->persist($checkout);
                $this->getDoctrine()->getManager()->flush();
                $contact = $this->contactRepository->findOne();
                $this->mailer->sendOrder($contact, $cart);
            } else {
                $this->getDoctrine()->getManager()->persist($checkout);
                $this->getDoctrine()->getManager()->flush();
            }
        } else {
            /** @var Payment $payment */
            $payment = $this->paymentRepository->findOneBy(['slug' => $ref]);
            if ($payment) {
                if ($code === '00000') {

                    $payment->setResponse($response);
                    $payment->setPayedAt(new \DateTime('now'));
                    $this->mailer->sendPayment($payment);
                } else {
                    $payment->setResponse($response);
                }

                $this->getDoctrine()->getManager()->persist($payment);
                $this->getDoctrine()->getManager()->flush();
            }
        }

        return new Response('', 200);

    }

    /**
     * @param Request $request
     * @Route("/request/monetico/responseAt", name="monetico_responseAt")
     *
     * @return Response
     * @throws \Doctrine\ORM\NonUniqueResultException
     * @throws \Twig\Error\LoaderError
     * @throws \Twig\Error\RuntimeError
     * @throws \Twig\Error\SyntaxError
     */
    public
    function MoneticoResponseAt(Request $request
    ) {
        if ($request->request->get('code-retour')) {

            $code = $request->request->get('code-retour', null);

        } else {
            $code = $request->query->get('code-retour', null);
        }

        if ($request->request->get('reference')) {

            $ref = $request->request->get('reference', null);

        } else {
            $ref = $request->query->get('reference', null);
        }

        if ($request->request->all()) {

            $response = $request->request->all();

        } else {
            $response = $request->query->all();
        }

        if (!$ref || !$code) {
            throw new BadRequestHttpException();
        }

        /** Accès au variant désactivé, si paiement effectué après la désactivation d'un variant  */
        $this->em->getFilters()->disable("soft_deletable");
        /** @var Cart $cart */
        $cart = $this->cartRepository->findOneBy(['token' => $ref]);
        if ($cart) {
            $checkout = $cart->getCartCheckout();
            $checkout->setResponse($response);
            if ($code === 'payetest' || $code === 'paiement') {
                $gift = $this->getDoctrine()->getManager()->getRepository(ProductGift::class)->findOneBy(['token' => $cart->getPromo()]);
                if ($gift) {
                    $gift->setUsedAt(new \DateTime('now'));
                }
                $checkout->setPayedAt(new \DateTime('now'));
                $this->getDoctrine()->getManager()->persist($checkout);
                $this->getDoctrine()->getManager()->flush();
                $contact = $this->contactRepository->findOne();
                $this->mailer->sendOrder($contact, $cart);
            } else {
                $this->getDoctrine()->getManager()->persist($checkout);
                $this->getDoctrine()->getManager()->flush();
            }

            return new Response('version=2'."\n".'cdr=0', 200);
        } else {
            /** @var Payment $payment */
            $payment = $this->paymentRepository->findOneBy(['slug' => $ref]);
            if ($payment) {
                if ($code === 'payetest' || $code === 'paiement') {
                    $payment->setPayedAt(new \DateTime('now'));
                    $payment->setResponse($response);
                    $this->mailer->sendPayment($payment);
                } else {
                    $payment->setResponse($response);
                }
                $this->getDoctrine()->getManager()->persist($payment);
                $this->getDoctrine()->getManager()->flush();

                return new Response('version=2'."\n".'cdr=0', 200);
            }
        }

        return new Response('version=2'."\n".'cdr=1'."\n", 200);


    }

    /**
     * @param Request $request
     * @Route("/request/sherlock/responseAt", name="sherlock_responseAt")
     *
     * @return Response
     * @throws \Doctrine\ORM\NonUniqueResultException
     * @throws \Twig\Error\LoaderError
     * @throws \Twig\Error\RuntimeError
     * @throws \Twig\Error\SyntaxError
     */
    public
    function SherlockResponseAt(Request $request
    ) {
        $message           = "message=".$request->request->get('DATA');
        $pathfile          = $this->sherlockFinder->getFileInfos("pathfile", "pathname");
        $path_bin_response = $this->sherlock_dir["sherlock_response_path"];
        $params            = "$path_bin_response pathfile=$pathfile $message";
        $result            = exec($params);
        $response          = explode("!", $result);
        $token             = $response[22];
        if ($this->sherlockPayment->valid($response)) {
            /** @var Cart $cart */
            $cart = $this->cartRepository->findOneBy(['token' => $token]);
            if ($cart) {
                $checkout = $cart->getCartCheckout();
                $checkout->setResponse($response);
                $checkout->setPayedAt(new \DateTime('now'));
                $this->em->persist($checkout);
                $this->em->flush();
                $contact = $this->contactRepository->findOne();
                $this->mailer->sendOrder($contact, $cart);

            } else {
                /** @var Payment $payment */
                $payment = $this->paymentRepository->findOneBy(['slug' => $token]);
                if ($payment) {
                    $payment->setResponse($response);
                    $payment->setPayedAt(new \DateTime('now'));
                    $this->em->persist($payment);
                    $this->em->flush();
                    $this->mailer->sendPayment($payment);
                }
            }
        } else {
            $cart = $this->cartRepository->findOneBy(['token' => $token]);
            if ($cart) {
                $checkout = $cart->getCartCheckout();
                $checkout->setResponse($response);
                $this->em->persist($checkout);
                $this->em->flush();
            } else {
                /** @var Payment $payment */
                $payment = $this->paymentRepository->findOneBy(['slug' => $token]);
                if ($payment) {
                    $payment->setResponse($response);
                    $this->em->persist($payment);
                    $this->em->flush();
                }
            }
        }

        return new Response('', 200);
    }

    /**
     * @param Request $request
     * @Route("/request/systempay/responseAt", name="systempay_responseAt")
     *
     * @return Response
     * @throws \Doctrine\ORM\NonUniqueResultException
     * @throws \Twig\Error\LoaderError
     * @throws \Twig\Error\RuntimeError
     * @throws \Twig\Error\SyntaxError
     */
    public
    function SystemPayResponseAt(Request $request
    ) {
        $response = $request->request->all();
        if ($response) {
            /** @var Cart $cart */
            $cart = $this->cartRepository->findOneBy(['token' => $response['vads_trans_id']]);
            if ($this->systempayPayment->valid($response)) {
                if ($cart) {
                    $checkout = $cart->getCartCheckout();
                    $checkout->setResponse($response);
                    $checkout->setPayedAt(new \DateTime('now'));
                    $this->em->persist($checkout);
                    $this->em->flush();
                    $contact = $this->contactRepository->findOne();
                    $this->mailer->sendOrder($contact, $cart);

                    return new Response('Order successfully updated');
                } else {
                    /** @var Payment $payment */
                    $payment = $this->paymentRepository->findOneBy(['slug' => $response['vads_trans_id']]);
                    if ($payment) {
                        $payment->setResponse($response);
                        $payment->setPayedAt(new \DateTime('now'));
                        $this->getDoctrine()->getManager()->persist($payment);
                        $this->getDoctrine()->getManager()->flush();
                        $this->mailer->sendPayment($payment);

                        return new Response('Order successfully updated');
                    }
                }

                return new Response('Data received but no cart associated');
            } else {
                if ($cart) {
                    $checkout = $cart->getCartCheckout();
                    $checkout->setResponse($response);
                    $this->em->persist($checkout);
                    $this->em->flush();
                } else {
                    /** @var Payment $payment */
                    $payment = $this->paymentRepository->findOneBy(['slug' => $response['vads_trans_id']]);
                    if ($payment) {
                        $payment->setResponse($response);
                        $this->getDoctrine()->getManager()->persist($payment);
                        $this->getDoctrine()->getManager()->flush();
                    }
                }

                return new Response('Payment refused');
            }
        }

        return new Response('POST is empty');
    }

    /**
     * @param Request $request
     * @Route("/request/sogecommerce/responseAt", name="sogecommerce_responseAt")
     *
     * @return Response
     * @throws \Doctrine\ORM\NonUniqueResultException
     * @throws \Twig\Error\LoaderError
     * @throws \Twig\Error\RuntimeError
     * @throws \Twig\Error\SyntaxError
     */
    public function SogeCommerceResponseAt(Request $request)
    {
        $response = $request->request->all();
        if ($response) {
            /** @var Cart $cart */
            $cart = $this->cartRepository->findOneBy(['token' => $response['vads_trans_id']]);
            if ($this->sogeCommercePayment->valid($response)) {
                if ($cart) {
                    $checkout = $cart->getCartCheckout();
                    $checkout->setResponse($response);
                    $checkout->setPayedAt(new \DateTime('now'));
                    $this->em->persist($checkout);
                    $this->em->flush();
                    $contact = $this->contactRepository->findOne();
                    $this->mailer->sendOrder($contact, $cart);

                    return new Response('Order successfully updated');
                } else {
                    /** @var Payment $payment */
                    $payment = $this->paymentRepository->findOneBy(['slug' => $response['vads_trans_id']]);
                    if ($payment) {
                        $payment->setResponse($response);
                        $payment->setPayedAt(new \DateTime('now'));
                        $this->getDoctrine()->getManager()->persist($payment);
                        $this->getDoctrine()->getManager()->flush();
                        $this->mailer->sendPayment($payment);

                        return new Response('Order successfully updated');
                    }
                }

                return new Response('Data received but no cart associated');
            } else {
                if ($cart) {
                    $checkout = $cart->getCartCheckout();
                    $checkout->setResponse($response);
                    $this->em->persist($checkout);
                    $this->em->flush();
                } else {
                    /** @var Payment $payment */
                    $payment = $this->paymentRepository->findOneBy(['slug' => $response['vads_trans_id']]);
                    if ($payment) {
                        $payment->setResponse($response);
                        $this->getDoctrine()->getManager()->persist($payment);
                        $this->getDoctrine()->getManager()->flush();
                    }
                }


                return new Response('Payment refused');
            }
        }

        return new Response('POST is empty');
    }

    /**
     * @param Request $request
     * @Route("/request/axepta/responseAt", name="axepta_responseAt")
     *
     * @return Response
     * @throws \Doctrine\ORM\NonUniqueResultException
     * @throws \Twig\Error\LoaderError
     * @throws \Twig\Error\RuntimeError
     * @throws \Twig\Error\SyntaxError
     */
    public function AxeptaResponseAt(Request $request)
    {
        $response = $request->request->all();
        if ($response) {
            $data = $this->axeptaPayment->valid($response);
            if (!empty($data)) {
                $cart = $this->cartRepository->findOneBy(['token' => $data['TransID']]);
                if ($data["Valid"] == true) {
                    if ($cart) {
                        $checkout = $cart->getCartCheckout();
                        $checkout->setResponse(array_merge($data, $response));
                        $checkout->setPayedAt(new \DateTime('now'));
                        $this->em->persist($checkout);
                        $this->em->flush();
                        $contact = $this->contactRepository->findOne();
                        $this->mailer->sendOrder($contact, $cart);

                        return new Response('Order successfully updated');
                    } else {
                        /** @var Payment $payment */
                        $payment = $this->paymentRepository->findOneBy(['slug' => $data['TransID']]);
                        if ($payment) {
                            $payment->setResponse(array_merge($data, $response));
                            $payment->setPayedAt(new \DateTime('now'));
                            $this->getDoctrine()->getManager()->persist($payment);
                            $this->getDoctrine()->getManager()->flush();
                            $this->mailer->sendPayment($payment);

                            return new Response('Order successfully updated');
                        }
                    }

                    return new Response('Data received but no cart associated');
                } else {
                    if ($cart) {
                        $checkout = $cart->getCartCheckout();
                        $checkout->setResponse(array_merge($data, $response));
                        $this->em->persist($checkout);
                        $this->em->flush();
                    } else {
                        /** @var Payment $payment */
                        $payment = $this->paymentRepository->findOneBy(['slug' => $data['TransID']]);
                        if ($payment) {
                            $payment->setResponse(array_merge($data, $response));
                            $this->getDoctrine()->getManager()->persist($payment);
                            $this->getDoctrine()->getManager()->flush();
                        }
                    }

                    return new Response('Payment refused');
                }
            }
        }

        return new Response('No response');
    }

    /**
     * @param Request $request
     * @Route("/request/sherlock2/responseAt", name="sherlock2_responseAt")
     *
     * @return Response
     * @throws \Doctrine\ORM\NonUniqueResultException
     * @throws \Twig\Error\LoaderError
     * @throws \Twig\Error\RuntimeError
     * @throws \Twig\Error\SyntaxError
     */
    public function Sherlock2ResponseAt(Request $request)
    {
        $response = $request->request->all();

        if ($response) {
            $data = $this->sherlock2Payment->valid($response);
            if (!empty($data)) {
                $cart = $this->cartRepository->findOneBy(['token' => $data['orderId']]);
                if ($data["Valid"] == true) {
                    if ($cart) {
                        $checkout = $cart->getCartCheckout();
                        $checkout->setResponse($response);
                        $checkout->setPayedAt(new \DateTime('now'));
                        $this->em->persist($checkout);
                        $this->em->flush();
                        $contact = $this->contactRepository->findOne();
                        $this->mailer->sendOrder($contact, $cart);

                        return new Response('Order successfully updated');
                    } else {
                        /** @var Payment $payment */
                        $payment = $this->paymentRepository->findOneBy(['slug' => $data['orderId']]);
                        if ($payment) {
                            $payment->setResponse($response);
                            $payment->setPayedAt(new \DateTime('now'));
                            $this->getDoctrine()->getManager()->persist($payment);
                            $this->getDoctrine()->getManager()->flush();
                            $this->mailer->sendPayment($payment);

                            return new Response('Order successfully updated');
                        }
                    }
                } else {
                    if ($cart) {
                        $checkout = $cart->getCartCheckout();
                        $checkout->setResponse($response);
                        $this->em->persist($checkout);
                        $this->em->flush();

                        return new Response('Data invalid');
                    } else {
                        /** @var Payment $payment */
                        $payment = $this->paymentRepository->findOneBy(['slug' => $data['orderId']]);
                        if ($payment) {
                            $payment->setResponse($response);
                            $this->getDoctrine()->getManager()->persist($payment);
                            $this->getDoctrine()->getManager()->flush();

                            return new Response('Data invalid');
                        }
                    }
                }
            }
        }

        return new Response('No response');
    }

    /**
     * @Route("/request/gift/{id}/check", name="gift_check")
     * @param null|ProductGift $gift
     * @return Response|void
     */
    public function scanGift(ProductGift $gift = null, Request $request)
    {
        $message = null;

        $form = $this->createForm(GiftCheckType::class);
        $form->handleRequest($request);

        if (empty($gift) || $gift->getUsedAt() != null || $gift->getValidUntilDate() < new \DateTime()) {
            switch ($gift) {
                case null:
                    $message = "Aucune carte cadeau n'as été trouvée";
                    break;
                case $gift->getUsedAt() != null:
                    $message = 'Cette carte cadeau a déjà été utilisée le '.$gift->getUsedAt()->format("d/m/Y").'!';
                    break;
                case $gift->getValidUntilDate() < new \DateTime():
                    $message = 'Cette carte cadeau a expiré le '.$gift->getValidUntilDate()->format("d/m/Y").' !';
            }

            return $this->render('gift/check.html.twig', [
                'message' => $message,
            ]);
        }

        if ($form->isSubmitted() && $form->isValid()) {
            $token = $form->getData()["token"];
            if ($this->shopConfigRepository->findBy(['giftCardCheckToken' => $token])) {
                $gift->setUsedAt(new \DateTime('now'));
                $this->em->persist($gift);
                $this->em->flush();
                $message = "Carte cadeau validée avec succès";

                return $this->render('gift/check.html.twig', [
                    'message' => $message,
                ]);
            } else {
                $message = "Ce code de validation est invalide";
            }
        }

        return $this->render('gift/check.html.twig', [
            'form'    => $form->createView(),
            'gift'    => $gift,
            'message' => $message,
        ]);
    }

    /**
     * @param Request $request
     * @Route("/request/payplug/responseAt", name="payplug_responseAt")
     *
     * @return Response
     * @throws \Doctrine\ORM\NonUniqueResultException
     * @throws \Twig\Error\LoaderError
     * @throws \Twig\Error\RuntimeError
     * @throws \Twig\Error\SyntaxError
     */
    public
    function PayPlugResponseAt(Request $request
    ) {
        $data = $request->toArray();
        if ($data['id']) {
            /** @var array $paymentArray */
            $paymentArray = $this->payplugPayment->valid($data);
            if ($paymentArray['is_paid']) {
                $cart = $this->cartRepository->findOneBy(['token' => $paymentArray['metadata']['transaction_id']]);
                if ($cart) {
                    $checkout = $cart->getCartCheckout();
                    $checkout->setResponse($paymentArray);
                    $checkout->setPayedAt(new \DateTime('now'));
                    $this->em->persist($checkout);
                    $this->em->flush();
                    $contact = $this->contactRepository->findOne();
                    $this->mailer->sendOrder($contact, $cart);
                    return new Response('Order successfully updated');
                } else {
                    /** @var Payment $payment */
                    $payment = $this->paymentRepository->findOneBy(['slug' => $paymentArray['metadata']['transaction_id']]);
                    if ($payment) {
                        $payment->setResponse($paymentArray);
                        $payment->setPayedAt(new \DateTime('now'));
                        $this->getDoctrine()->getManager()->persist($payment);
                        $this->getDoctrine()->getManager()->flush();
                        $this->mailer->sendPayment($payment);

                        return new Response('Order successfully updated');
                    }
                }
            }else {
                if ($cart) {
                    $checkout = $cart->getCartCheckout();
                    $checkout->setResponse($paymentArray);
                    $this->em->persist($checkout);
                    $this->em->flush();
                    return new Response('Data invalid');
                } else {
                    /** @var Payment $payment */
                    $payment = $this->paymentRepository->findOneBy(['slug' => $paymentArray['metadata']['transaction_id']]);
                    if ($payment) {
                        $payment->setResponse($paymentArray);
                        $this->getDoctrine()->getManager()->persist($payment);
                        $this->getDoctrine()->getManager()->flush();
                        return new Response('Data invalid');
                    }
                }
            }
        }
        return new Response('No response');
    }

    /**
     * @param Request $request
     * @Route("/request/cawl/responseAt", name="cawl_responseAt")
     *
     * @return Response
     * @throws \Doctrine\ORM\NonUniqueResultException
     * @throws \Twig\Error\LoaderError
     * @throws \Twig\Error\RuntimeError
     * @throws \Twig\Error\SyntaxError
     */
    function CawlResponseAt(Request $request)
    {
        $signature   = $request->headers->get('X-GCS-Signature');
        $rawBody     = $request->getContent();
        $result      = json_decode($rawBody, true);
        $valid = $this->cawlPayment->valid($rawBody, $signature);
        $reference = $result['payment']['paymentOutput']['references']['merchantReference'];
        if ($valid == true) {
            $cart = $this->cartRepository->findOneBy(['token' => $reference]);
            if ($cart) {
                $checkout = $cart->getCartCheckout();
				$result['signature'] = $signature;
                $checkout->setResponse($result);
                $checkout->setPayedAt(new \DateTime('now'));
                $this->em->persist($checkout);
                $this->em->flush();
                $contact = $this->contactRepository->findOne();
                $this->mailer->sendOrder($contact, $cart);

                return new Response('Order successfully updated', 200);
            } else {
                /** @var Payment $payment */
                $payment = $this->paymentRepository->findOneBy(['slug' => $reference]);
                if ($payment) {
                    $payment->setResponse($result);
                    $payment->setPayedAt(new \DateTime('now'));
                    $this->getDoctrine()->getManager()->persist($payment);
                    $this->getDoctrine()->getManager()->flush();
                    $this->mailer->sendPayment($payment);

                    return new Response('Order successfully updated', 200);
                }
            }
        } else {
            $cart = $this->cartRepository->findOneBy(['token' => $reference]);
            if ($cart) {
                $checkout = $cart->getCartCheckout();
				$result['signature'] = $signature;
                $checkout->setResponse($result);
                $this->em->persist($checkout);
                $this->em->flush();

                return new Response('Received', 200);
            } else {
                /** @var Payment $payment */
                $payment = $this->paymentRepository->findOneBy(['slug' => $reference]);
                if ($payment) {
                    $payment->setResponse($result);
                    $this->getDoctrine()->getManager()->persist($payment);
                    $this->getDoctrine()->getManager()->flush();
                    $this->mailer->sendPayment($payment);

                    return new Response('Received', 200);
                }
            }
        }

        return new Response('No response', 200);
    }
}
