<?php

namespace Lc\ShopBundle\Services ;

use App\Entity\Product;
use Doctrine\ORM\EntityManagerInterface;
use Lc\ShopBundle\Context\PriceUtilsInterface;
use Lc\ShopBundle\Context\ProductCategoryInterface;
use Lc\ShopBundle\Context\ProductFamilyInterface;
use Lc\ShopBundle\Context\ProductInterface;
use Lc\ShopBundle\Context\ReductionCatalogInterface;
use Lc\ShopBundle\Model\ProductFamily;

class ProductFamilyUtils
{
        protected $priceUtils ;
        protected $em ;

        public function __construct(PriceUtilsInterface $priceUtils, EntityManagerInterface $em)
        {
                $this->priceUtils = $priceUtils ;
                $this->em = $em;
        }

        public function getCheapestProduct($productFamily)
        {
                $priceUtils = $this->priceUtils ;
                return $this->getCheapestOrMostExpensiveProduct($productFamily, function ($a, $b) use ($priceUtils) {
                        return $priceUtils->getPriceWithTaxAndReduction($a) > $priceUtils->getPriceWithTaxAndReduction($b) ;
                }, true);
        }

        public function getCheapestProductByRefUnit($productFamily)
        {
                $priceUtils = $this->priceUtils ;
                return $this->getCheapestOrMostExpensiveProduct($productFamily, function ($a, $b) use ($priceUtils) {
                        return $priceUtils->getPriceByRefUnitWithTaxAndReduction($a) > $priceUtils->getPriceByRefUnitWithTaxAndReduction($b) ;
                }, false);
        }

        public function getMostExpensiveProductByRefUnit($productFamily)
        {
                $priceUtils = $this->priceUtils ;
                return $this->getCheapestOrMostExpensiveProduct($productFamily, function ($a, $b) use ($priceUtils) {
                        return $priceUtils->getPriceByRefUnitWithTaxAndReduction($a) < $priceUtils->getPriceByRefUnitWithTaxAndReduction($b) ;
                }, false);
        }

        private function getCheapestOrMostExpensiveProduct($productFamily, $comparisonFunction, $returnSelfIfNotActiveProducts)
        {
                if($productFamily->getActiveProducts()) {
                        $products = $productFamily->getProductsOnline()->getValues();
                        if (count($products) > 0) {
                                usort($products, $comparisonFunction);
                                return $products[0];
                        }
                }else{
                        return $productFamily->getOriginProduct();
                }
                if ($returnSelfIfNotActiveProducts) {
                        return $productFamily;
                }
                else {
                        return false;
                }
        }



        public function processBeforePersistProductFamily($productFamily, $editForm=false, $clone =false){
                if($editForm){
                        $this->processReductionCatalog($productFamily, $editForm);
                        $this->processCategories($productFamily);
                }
                $this->processProducts($productFamily, $clone);
                $this->processPrice($productFamily);

                return $productFamily;
        }

        protected function processReductionCatalog($entity, $editForm)
        {
                $reductionCatalog = $editForm->get('reductionCatalog')->getData();
                if ($reductionCatalog instanceof ReductionCatalogInterface) {
                        if ($reductionCatalog->getValue() && $reductionCatalog->getBehaviorTaxRate() && $reductionCatalog->getUnit()) {
                                $reductionCatalog->setMerchant($entity->getMerchant());
                                $reductionCatalog->setStatus($editForm->get('activeReductionCatalog')->getData());
                                $reductionCatalog->setProductFamily($entity);
                                $this->em->persist($reductionCatalog);
                        }
                }
        }

        protected function processPrice($entity)
        {
                if ($entity->getBehaviorPrice() == 'by-piece') {
                        $entity->setPriceByRefUnit(null);
                        $entity->setBuyingPriceByRefUnit(null);
                } else if ($entity->getBehaviorPrice() == 'by-reference-unit') {
                        $entity->setPrice(null);
                        $entity->setBuyingPrice(null);
                }
        }

        protected function processProducts($entity, $clone = false)
        {
                if($clone) {
                        foreach ($entity->getProducts() as $i => $product) {
                                $newProduct = clone $product;
                                $newProduct->setProductFamily($entity);
                                $this->em->persist($newProduct);
                                $entity->addProduct($newProduct);
                        }
                }else {
                        //Récupère le product origin
                        $originProducts = $this->em->getRepository(ProductInterface::class)->findBy(array(
                                'productFamily' => $entity->getId(),
                                'originProduct' => true
                        ));


                        if (count($originProducts) > 1) {
                                throw new \ErrorException('Plusieurs OriginProduct pour un même produit... Contacter fab');

                                // Case Nouveau product family
                        } else if (count($originProducts) == 0) {
                                $originProduct = new Product();
                                $originProduct->setProductFamily($entity);
                                $originProduct->setOriginProduct(true);
                                $entity->addProduct($originProduct);
                        } else {
                                $originProduct = $originProducts[0];
                        }

                        if ($entity->getActiveProducts()) {
                                $originProduct->setStatus(-1);
                        } else {
                                $originProduct->setStatus(1);
                        }

                        //Enregistrement
                        $entity->addProduct($originProduct);

                        foreach ($entity->getProducts() as $product) {
                                $product->setProductFamily($entity);
                                $this->em->persist($product);
                                $entity->addProduct($product);
                        }
                }

        }

        protected function processCategories(ProductFamilyInterface $entity)
        {
                $productCategoryRepository = $this->em->getRepository(ProductCategoryInterface::class);
                $productCategories = $entity->getProductCategories();

                $entity->initProductCategories();

                foreach ($productCategories as $key => $bool) {
                        if (is_bool($bool) && $bool) {
                                if (strpos($key, 'category_children_') !== false) {
                                        $idCategory = (int)str_replace('category_children_', '', $key);
                                } else {
                                        $idCategory = (int)str_replace('category_', '', $key);
                                }

                                $category = $productCategoryRepository->find($idCategory);
                                $entity->addProductCategory($category);
                        }
                }
        }

}