<?php

namespace Lc\ShopBundle\Repository;

use App\Entity\DeliveryAvailabilityPointSale;
use App\Entity\DeliveryAvailabilityZone;
use Doctrine\ORM\Query\Expr\Join;
use Doctrine\ORM\QueryBuilder;
use Lc\ShopBundle\Context\DefaultRepositoryInterface;
use Lc\ShopBundle\Context\OrderShopInterface;
use Lc\ShopBundle\Model\OrderStatus;

/**
 * @method OrderShopInterface|null find($id, $lockMode = null, $lockVersion = null)
 * @method OrderShopInterface|null findOneBy(array $criteria, array $orderBy = null)
 * @method OrderShopInterface[]    findAll()
 * @method OrderShopInterface[]    findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
 */
class OrderShopRepository extends BaseRepository implements DefaultRepositoryInterface
{

        public function getInterfaceClass()
        {
                return OrderShopInterface::class;
        }

        public function countValidOrderWithReductionCredit($reductionCredit, $user)
        {
                $query = $this->findByMerchantQuery();
                $query = $this->filterOrderValid($query);
                $query->select('count(e.id)');
                $query->andWhere('e.user = :user');
                $query->innerJoin('e.orderReductionCredits', 'orc');
                $query->andWhere('orc.reductionCredit = :reductionCredit');
                $query->setParameter('reductionCredit', $reductionCredit);
                $query->setParameter('user', $user);
                return $query->getQuery()->getSingleScalarResult();
        }


        public function countValidOrderWithReductionCart($reductionCart)
        {
                $query = $this->findByMerchantQuery();
                $query = $this->filterOrderValid($query);
                $query->select('count(e.id)');
                $query->join('e.orderReductionCarts', 'orc');
                $query->andWhere('orc.reductionCart = :reductionCart');
                $query->setParameter('reductionCart', $reductionCart);
                return $query->getQuery()->getSingleScalarResult();
        }


        public function countValidOrderWithReductionCartPerUser($reductionCart, $user)
        {
                $query = $this->findByMerchantQuery();
                $query = $this->filterOrderValid($query);
                $query->select('count(e.id)');
                $query->andWhere('e.user = :user');
                $query->join('e.orderReductionCarts', 'orc');
                $query->andWhere('orc.reductionCart = :reductionCart');
                $query->setParameter('reductionCart', $reductionCart);
                $query->setParameter('user', $user);
                return $query->getQuery()->getSingleScalarResult();
        }


        public function filterOrderValid(?QueryBuilder $query): QueryBuilder
        {
                return $this->_filterOrderStatus($query, OrderStatus::$statusAliasAsValid) ;
        }

        public function filterOrderWaitingDelivery($query)
        {
                return $this->_filterOrderStatus($query, OrderStatus::$statusAliasWaitingDelivery) ;
        }

        public function filterOrderCart($query)
        {
                return $this->_filterOrderStatus($query, OrderStatus::$statusAliasAsCart) ;
        }

        private function _filterOrderStatus($query, $statusArray) {
                $query->leftJoin('e.orderStatus', 'os');
                $query->andWhere('os.alias IN (:alias)');
                $query->setParameter('alias',$statusArray);
                return $query ;
        }

        public function findCartCurrent($params)
        {
                $query = $this->findByMerchantQuery();


                if (isset($params['user'])) {
                        $query->andWhere('e.user = :user')->setParameter('user', $params['user']);
                }

                if (isset($params['visitor'])) {
                        $query->andWhere('e.visitor = :visitor')->setParameter('visitor', $params['visitor']);
                }

                $query = $this->filterOrderCart($query);

                $query->leftJoin('e.orderReductionCarts', 'orderReductionCarts')
                        ->addSelect('orderReductionCarts');

                $results = $query->getQuery()->getResult();

                if ($results) {
                        return $results[0];
                }

                return null;
        }

        public function findAllBy($params = [])
        {
                $query = $this->findByMerchantQuery();

                if (isset($params['count']) && $params['count']) {
                        $query->select('count(e.id)');
                }

                if (isset($params['select'])) {
                        $query->select( $params['select']);
                }

                if (isset($params['dateStart']) || isset($params['dateEnd'])) {
                        $params['dateField'] = isset($params['dateField']) ? $params['dateField'] : 'validationDate';
                }

                if (isset($params['dateStart'])) {
                        $query->andWhere('e.' . $params['dateField'] . ' >= :dateStart')->setParameter('dateStart', $params['dateStart']);
                }
                if (isset($params['dateEnd'])) {
                        $query->andWhere('e.' . $params['dateField'] . ' <= :dateEnd')->setParameter('dateEnd', $params['dateEnd']);
                }

                if (isset($params['weekNumber'])) {
                        $query->andWhere('e.weekNumber = :weekNumber')->setParameter('weekNumber', $params['weekNumber']);
                }

                if (isset($params['isCart'])) {
                        $query = $this->filterOrderCart($query);
                }

                if (isset($params['isValid'])) {
                        $query = $this->filterOrderValid($query);
                }

                if (isset($params['isWaitingDelivery'])) {
                        $query = $this->filterOrderWaitingDelivery($query);
                }

                if (isset($params['orderStatus'])) {
                        $query->leftJoin('e.orderStatus', 'os');
                        $query->andWhere('os.alias LIKE :alias');
                        $query->setParameter('alias', $params['orderStatus']);
                }

                if (isset($params['user'])) {
                        $query->andWhere('e.user = :user')->setParameter('user', $params['user']);
                }

                if(isset($params['address'])) {
                        $query->andWhere('e.deliveryAddress = :address OR e.invoiceAddress = :address')->setParameter('address', $params['address']);
                }

                if(isset($params['weekDeliveryTrucks'])) {
                        $query->andWhere('e.weekDeliveryTruck IN (:weekDeliveryTrucks)')->setParameter('weekDeliveryTrucks', $params['weekDeliveryTrucks']);
                }

                if(isset($params['estimatedDeliveryDateTime'])) {
                        $query->andWhere('e.estimatedDeliveryDateTime >= :deliveryDateStart');
                        $query->andWhere('e.estimatedDeliveryDateTime < :deliveryDateEnd');
                        $date = clone $params['estimatedDeliveryDateTime'];
                        $query->setParameter('deliveryDateStart', $date->format('Y-m-d 00:00:00'));
                        $query->setParameter('deliveryDateEnd', $date->modify('+1 day')->format('Y-m-d 00:00:00'));
                }

                if(isset($params['deliveryDate'])) {
                        $query->andWhere('e.deliveryDate >= :deliveryDateStart');
                        $query->andWhere('e.deliveryDate < :deliveryDateEnd');
                        $date = clone $params['deliveryDate'];
                        $query->setParameter('deliveryDateStart', $date->format('Y-m-d 00:00:00'));
                        $query->setParameter('deliveryDateEnd', $date->modify('+1 day')->format('Y-m-d 00:00:00'));
                }

                if (isset($params['mergeComplementaryOrderShops'])) {
                        $query->andWhere('e.mainOrderShop IS NULL');
                        $query->leftJoin('e.complementaryOrderShops', 'complementaryOrderShops');
                }

                if (isset($params['excludeComplementaryOrderShops'])) {
                        $query->andWhere('e.mainOrderShop IS NULL');
                }

                $setParameterHorsTournee = false ;

                if (isset($params['isCircuit'])) {
                        $query->leftJoin('e.deliveryPointSale', 'pointSale');
                        $query->andWhere('e.deliveryPointSale IS NULL OR (pointSale.isDepository = 0 AND (pointSale.devAlias IS NULL OR pointSale.devAlias != :devAliasHorsTournee))');
                        $setParameterHorsTournee = true ;
                }

                if (isset($params['isDepository'])) {
                        $query->innerJoin('e.deliveryPointSale', 'pointSale');
                        $query->andWhere('pointSale IS NOT NULL AND pointSale.isDepository = 1 AND (pointSale.devAlias IS NULL OR pointSale.devAlias != :devAliasHorsTournee)');
                        $setParameterHorsTournee = true ;
                }

                if (isset($params['isOffCircuit'])) {
                        $query->innerJoin('e.deliveryPointSale', 'pointSale');
                        $query->andWhere('pointSale IS NOT NULL AND pointSale.devAlias = :devAliasHorsTournee');
                        $setParameterHorsTournee = true ;
                }

                if($setParameterHorsTournee) {
                        $query->setParameter('devAliasHorsTournee', 'horstournee') ;
                }

                if (isset($params['deliveryAvailability'])) {
                        $deliveryAvailability = $params['deliveryAvailability'] ;

                        $deliveryAvailabilityZone = ($deliveryAvailability instanceof DeliveryAvailabilityZone) ? $deliveryAvailability : false;
                        $deliveryAvailabilityPointSale = ($deliveryAvailability instanceof DeliveryAvailabilityPointSale) ? $deliveryAvailability : false;

                        if($deliveryAvailabilityZone){
                                $query->andWhere('e.deliveryAvailabilityZone = :deliveryAvailabilityZone');
                                $query->setParameter('deliveryAvailabilityZone', $deliveryAvailabilityZone);
                        }

                        if($deliveryAvailabilityPointSale) {
                                $query->andWhere('e.deliveryAvailabilityPointSale = :deliveryAvailabilityPointSale');
                                $query->setParameter('deliveryAvailabilityPointSale', $deliveryAvailabilityPointSale);
                        }
                }
                else{
                        $query->leftJoin('e.deliveryAvailabilityZone', 'deliveryAvailabilityZone');
                        $query->leftJoin('deliveryAvailabilityZone.deliverySlot', 'deliverySlotZone');

                        $query->leftJoin('e.deliveryAvailabilityPointSale', 'deliveryAvailabilityPointSale');
                        $query->leftJoin('deliveryAvailabilityPointSale.deliverySlot', 'deliverySlotPointSale');
                }

                if (isset($params['orderBy'])) {
                        $query->orderBy('e.' . $params['orderBy'], isset($params['orderByDirection']) ? $params['orderByDirection'] : 'DESC');
                } else {
                        $query->orderBy('e.id', 'DESC');
                }


                if (isset($params['groupBy'])) {
                        $query->groupBy( $params['groupBy']);
                }

                if (isset($params['count']) && $params['count']) {
                        return $query->getQuery()->getSingleScalarResult();
                } else {
                        return $query->getQuery()->getResult();
                }
        }

        public function findLastOrderValidOfWeek($weekNumber)
        {
                $query = $this->findByMerchantQuery();
                $query = $this->filterOrderValid($query);
                $query->andWhere('e.weekNumber = :weekNumber');
                $query->andWhere('e.mainOrderShop = false OR  e.mainOrderShop IS NULL');
                $query->setParameter('weekNumber', $weekNumber);
                $query->orderBy('e.weekId', 'DESC');
                $query->setMaxResults(1);

                return $query->getQuery()->getOneOrNullResult();

        }

        public function findLastOrderValid()
        {
                $query = $this->findByMerchantQuery();
                $query = $this->filterOrderValid($query);
                $query->andWhere('e.mainOrderShop = false OR  e.mainOrderShop IS NULL');
                $query->orderBy('e.idValidOrder', 'DESC');
                $query->setMaxResults(1);

                return $query->getQuery()->getOneOrNullResult();

        }


        public function countValidOrderProductsOfWeekByProduct($weekNumber, $productId)
        {
                $query = $this->findByMerchantQuery();
                $query = $this->filterOrderValid($query);
                $query->andWhere('e.weekNumber = :weekNumber');
                $query->setParameter('weekNumber', $weekNumber);
                $query->leftJoin('e.orderProducts', 'orderProduct');
                $query->andWhere('orderProduct.product = :product');
                $query->setParameter('product', $productId);
                $query->select('SUM(orderProduct.quantityOrder) as quantity');

                $result = $query->getQuery()->getOneOrNullResult();
                return $result['quantity'];

        }
}
