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

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

use CpCreation\VitiCore\Bridge\Symfony\Bundle\Form\Site\CartType;
use CpCreation\VitiCore\Bridge\Symfony\Bundle\Manager\PaymentProviderManager;
use CpCreation\VitiCore\Bridge\Symfony\Bundle\Utils\CalculShipping;
use CpCreation\VitiCore\Bridge\Symfony\Bundle\Utils\PriceGroupWithCookie;
use CpCreation\VitiCore\Cart\Model\Cart;
use CpCreation\VitiCore\Cart\Model\CartCheckout;
use CpCreation\VitiCore\Cart\Model\CartItem;
use CpCreation\VitiCore\Cart\Repository\CartRepository;
use CpCreation\VitiCore\Contact\Repository\ContactRepository;
use CpCreation\VitiCore\Payment\Repository\PaymentRepository;
use CpCreation\VitiCore\Popup\Repository\PopupRepository;
use CpCreation\VitiCore\Product\Model\Product;
use CpCreation\VitiCore\Product\Model\ProductVariant;
use CpCreation\VitiCore\Product\Repository\ProductCategoryRepository;
use CpCreation\VitiCore\Product\Repository\ProductDegressiveRepository;
use CpCreation\VitiCore\Product\Repository\ProductPriceCodeRepository;
use CpCreation\VitiCore\Product\Repository\ProductPriceGroupRepository;
use CpCreation\VitiCore\Product\Repository\ProductTaxRepository;
use CpCreation\VitiCore\Shop\Model\DeliveryMethod;
use CpCreation\VitiCore\Shop\Repository\ShippingConfigRepository;
use CpCreation\VitiCore\Shop\Repository\ShopConfigRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\FormError;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Session\Flash\FlashBagInterface;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Contracts\Translation\TranslatorInterface;

class ShopController extends AbstractController
{
    private $productPriceCodeRepository;
    private $productPriceGroupRepository;
    private $productTaxRepository;
    private $shopConfigRepository;
    private $shippingConfigRepository;
    private $cartRepository;
    private $paymentRepository;
    private $contactRepository;
    private $calculShipping;
    private $priceGroupWithCookie;
    private $paymentProviderManager;
    private $session;
    private $flashBag;
    private $translator;
    private $productCategoryRepository;
    private $popupRepository;
    private $productDegressiveRepository;

    public function __construct(ProductPriceCodeRepository $productPriceCodeRepository,
        ProductPriceGroupRepository $productPriceGroupRepository,
        ProductTaxRepository $productTaxRepository,
        ShopConfigRepository $shopConfigRepository,
        ShippingConfigRepository $shippingConfigRepository,
        ProductDegressiveRepository $productDegressiveRepository,
        CartRepository $cartRepository,
        PaymentRepository $paymentRepository,
        ContactRepository $contactRepository,
        CalculShipping $calculShipping,
        PriceGroupWithCookie $priceGroupWithCookie,
        PaymentProviderManager $paymentProviderManager,
        SessionInterface $session,
        FlashBagInterface $flashBag,
        TranslatorInterface $translator,
        ProductCategoryRepository $productCategoryRepository,
        PopupRepository $popupRepository
    ) {
        $this->productPriceCodeRepository  = $productPriceCodeRepository;
        $this->productPriceGroupRepository = $productPriceGroupRepository;
        $this->productTaxRepository        = $productTaxRepository;
        $this->shopConfigRepository        = $shopConfigRepository;
        $this->shippingConfigRepository    = $shippingConfigRepository;
        $this->cartRepository              = $cartRepository;
        $this->paymentRepository           = $paymentRepository;
        $this->contactRepository           = $contactRepository;
        $this->calculShipping              = $calculShipping;
        $this->paymentProviderManager      = $paymentProviderManager;
        $this->priceGroupWithCookie        = $priceGroupWithCookie;
        $this->session                     = $session;
        $this->flashBag                    = $flashBag;
        $this->translator                  = $translator;
        $this->productCategoryRepository   = $productCategoryRepository;
        $this->popupRepository             = $popupRepository;
        $this->productDegressiveRepository = $productDegressiveRepository;
    }

    /**
     * @param Request   $request
     * @param Cart|null $cart
     *
     * @return mixed|\Symfony\Component\HttpFoundation\Response
     * @throws \Doctrine\ORM\NonUniqueResultException
     */
    public
    function indexAction(Request $request,
        Cart $cart = null
    ) {

        $popup      = $this->popupRepository->findOneOrNull();
        $groupPrice = null;
        if ($this->session->get('groupPrice')) {
            $groupPrice = $this->productPriceGroupRepository->findOneBy(['id' => $this->session->get('groupPrice')]);
            if (!$groupPrice) {
                return $this->redirectToRoute('price_code_delete');
            }
        }
        $priceGroups    = $this->productPriceGroupRepository->findNotSoftDeletable();
        $products       = $this->priceGroupWithCookie->findAllPublish();
        $taxDefault     = $this->productTaxRepository->findOneBy(['byDefault' => true]);
        $shippingConfig = $this->shippingConfigRepository->findOne();
        $categories     = $this->productCategoryRepository->findOnlyShop($groupPrice);
        $config         = $this->shopConfigRepository->findOne();
        if ($this->session->get('cart')) {
            $cart = $this->cartRepository->findOneBy(['id' => $this->session->get('cart')]);
            /** @var CartCheckout $cartCheckout */
            if ($cart) {
                $cartCheckout = $cart->getCartCheckout();
                if ($cartCheckout) {
                    if ($cartCheckout->getPayedAt()) {
                        $cart = null;
                        $this->get('session')->set('cart', null);
                    }
                }
            }
        }

        $form = $this->createForm(CartType::class, $cart);
        $form->handleRequest($request);
        if ($form->isSubmitted() && $form->isValid()) {

            /** @var Cart $cart */
            $cart = $form->getData();
            $cart->setToken();
            $items = $cart->getItems();
            /** @var CartItem $item */
            foreach ($items as $item) {
                $variant = $item->getVariant();
                $item->setCart($cart);
                if ($variant->getPriceDiscount()) {
                    $item->setPrice($variant->getPriceDiscount());
                } else {
                    $item->setPrice($variant->getPrice());
                }

            }

            try {

                $shipping = $this->calculShipping->shippingTotalPrice($cart);
                $cart->setShipping($shipping['amount']);
                $cart->setShippingName($shipping['shippingName']);
                $this->cartRepository->save($cart);
                $this->session->set('cart', $cart->getId()->toString());
                $contact = $this->contactRepository->findOne();

                return $this->paymentProviderManager->createPaymentProviderManager($contact, $cart);

            } catch (\Exception $e) {
                $form->addError(new FormError($e->getMessage()));
                $this->flashBag->add('error', $e->getMessage());
            }
        } elseif ($form->isSubmitted()) {
            $this->flashBag->add('error', 'Le formulaire n\'est pas rempli correctement !');
        }

        /** @var Product $product */
        foreach ($products as $product) {
            $degressivities = $this->productDegressiveRepository->findAllByProductAndByGroup($product, $groupPrice);
            if ($degressivities) {
                $product->setDegressivities($degressivities);
            }
        }

        return $this->render(
            'shop.html.twig',
            [
                'classMenu'      => 'black',
                'products'       => $products,
                'config'         => $config,
                'priceGroups'    => $priceGroups,
                'taxDefault'     => $taxDefault,
                'shippingConfig' => $shippingConfig,
                'categories'     => $categories,
                'popup'          => $popup,
                'form'           => $form->createView(),
            ]
        );
    }

    /**
     * @param DeliveryMethod $deliveryMethod
     * @Route("/request/delivery_method/{id}/products", options={"expose"=true}, name="delivery_method_products")
     *
     * @return JsonResponse
     */
    public
    function viewDeliveryProducts(DeliveryMethod $deliveryMethod
    ) {
        $data     = [];
        $iterator = $deliveryMethod->getProductVariants()->getIterator();
        $iterator->uasort(function ($a, $b) {
            return ($a->getProduct()->getPosition() < $b->getProduct()->getPosition()) ? -1 : 1;
        });
        $collection = new ArrayCollection(iterator_to_array($iterator));
        /** @var ProductVariant $variant */
        foreach ($collection as $variant) {
            $data[] = $variant->getName();
        }

        return new JsonResponse($data);
    }
}
