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

namespace CpCreation\VitiCore\Product\Repository;

use CpCreation\VitiCore\Behavior\HasDisable;
use CpCreation\VitiCore\Behavior\IsSoftDeletable;
use CpCreation\VitiCore\Product\Model\Product;
use CpCreation\VitiCore\Product\Model\ProductCategory;
use CpCreation\VitiCore\Product\Model\ProductPriceGroup;
use CpCreation\VitiCore\Repository\BaseRepository;
use Doctrine\ORM\Query\Expr\Join;
use Doctrine\Persistence\ManagerRegistry;

class ProductRepository extends BaseRepository
{
    /**
     * ProductRepository constructor.
     * @param ManagerRegistry $registry
     * @throws \ReflectionException
     */
    public function __construct(ManagerRegistry $registry)
    {
        parent::__construct($registry, Product::class);
    }

    public function findAllNotDeleted()
    {
        $qb = $this->createQueryBuilder('product')
                   ->addSelect('va')
                   ->innerJoin('product.variants', 'va', Join::WITH, 'va.deletedAt IS NULL')
                   ->orderBy('product.position', 'ASC');


        return $qb->getQuery()->getResult();
    }

    public function findAllPublish($group = null, ProductCategory $category = null)
    {
        $qb = $this->createQueryBuilder('product')
                   ->addSelect('tr, im, im2, ca, va, ty, tytr, pr')
                   ->innerJoin('product.translations', 'tr', Join::WITH, 'tr.translatable = product.id')
                   ->leftJoin('product.category', 'ca', Join::WITH, 'ca.id = product.category')
                   ->innerJoin('product.image', 'im', Join::WITH, 'im.id = product.image')
                   ->leftJoin('product.secondImage', 'im2', Join::WITH, 'im2.id = product.secondImage')
                   ->innerJoin('product.variants', 'va', Join::WITH, '(va.unPublished = FALSE and va.deletedAt IS NULL)')
                   ->innerJoin('va.prices', 'pr')
                   ->innerJoin('va.type', 'ty')
                   ->innerJoin('ty.translations', 'tytr')
                   ->andWhere('product.disabled = FALSE')
                   ->andWhere('product.deletedAt is NULL')
                   ->orderBy('product.position', 'ASC');


        if ($category) {
            $qb
                ->andWhere('product.category = :category')
                ->setParameter('category', $category);
        }

        if ($group) {
            $qb
                ->innerJoin('product.groups', 'gr', Join::WITH, 'gr.id = :group.id')
                ->setParameter('group', $group);
        }

        return $qb->getQuery()->getResult();
    }

    public function findOnlyCuvee($category = null)
    {
        if ($category) {
            $qb = $this->createQueryBuilder('product')
                       ->addSelect('tr,im')
                       ->innerJoin('product.translations', 'tr', Join::WITH, 'tr.translatable = product.id')
                       ->innerJoin('product.image', 'im', Join::WITH, 'im.id = product.image')
                       ->andWhere('product.category = :category')
                       ->andWhere('product.disabled = FALSE')
                       ->andWhere('product.deletedAt is NULL')
                       ->andWhere('product.cuvee = TRUE')
                       ->orderBy('product.position', 'ASC')
                       ->setParameter('category', $category)
                       ->getQuery();

            return $qb->execute();
        }

        $qb = $this->createQueryBuilder('product')
                   ->addSelect('tr, im')
                   ->innerJoin('product.translations', 'tr')
                   ->innerJoin('product.image', 'im')
                   ->innerJoin('product.category', 'cat')
                   ->andWhere('product.disabled = FALSE')
                   ->andWhere('product.deletedAt is NULL')
                   ->andWhere('cat.pageCuvee = TRUE')
                   ->andWhere('product.cuvee = TRUE')
                   ->addOrderBy('cat.position', 'ASC')
                   ->addOrderBy('product.position', 'ASC')
                   ->getQuery();

        return $qb->execute();

    }

    public function findOnlyShop($group = null, $category = null)
    {
        $qb = $this->createQueryBuilder('product')
                   ->addSelect('tr,im')
                   ->innerJoin('product.translations', 'tr', Join::WITH, 'tr.translatable = product.id')
                   ->innerJoin('product.image', 'im', Join::WITH, 'im.id = product.image')
                   ->innerJoin('product.variants', 'va', Join::WITH, '(va.unPublished = FALSE and va.deletedAt IS NULL)')
                   ->innerJoin('va.type', 'type', Join::WITH, 'type.id = va.type')
                   ->innerJoin('product.category', 'cat')
                   ->andWhere('cat.pageShop = TRUE')
                   ->andWhere('product.disabled = FALSE')
                   ->andWhere('product.deletedAt is NULL')
                   ->andWhere('product.shop = TRUE')
                   ->orderBy('product.positionShop', 'ASC');

        
        if ($category) {
            $qb
                ->andWhere('product.category = :category')
                ->setParameter('category', $category);
        }

        if ($group) {
            $qb
                ->innerJoin('product.groups', 'gr', Join::WITH, 'gr.id = :group')
                ->setParameter('group', $group);
        }

        return $qb->getQuery()->getResult();

    }

    public function findByPositionShopOrderAdmin()
    {
        $qb = $this->createQueryBuilder('r')
                   ->orderBy('r.positionShop', 'ASC');
        $qb->andWhere('r.deletedAt is NULL');

        $query = $qb->getQuery();

        return $query->execute();
    }

    public function findByPositionShopOrder()
    {
        $qb = $this->createQueryBuilder('r')
                   ->orderBy('r.positionShop', 'ASC');
        $qb->andWhere('r.deletedAt is NULL');
        $qb->andWhere('r.disabled = FALSE');
        $query = $qb->getQuery();

        return $query->execute();
    }

    public function findNextCuvee(int $position)
    {
        $qb = $this->createQueryBuilder('product')
                   ->innerJoin('product.category', 'cat')
                   ->andWhere('product.disabled = FALSE')
                   ->andWhere('product.deletedAt is NULL')
                   ->andWhere('cat.pageCuvee = TRUE')
                   ->andWhere('product.cuvee = TRUE')
                   ->andWhere('product.position > :position')
                   ->addOrderBy('cat.position', 'ASC')
                   ->addOrderBy('product.position', 'ASC')
                   ->setMaxResults(1)
                   ->setParameter('position', $position)
                   ->getQuery();

        return $qb->getOneOrNullResult();
    }

    public function findPreviousCuvee(int $position)
    {
        $qb = $this->createQueryBuilder('product')
                   ->innerJoin('product.category', 'cat')
                   ->andWhere('product.disabled = FALSE')
                   ->andWhere('product.deletedAt is NULL')
                   ->andWhere('cat.pageCuvee = TRUE')
                   ->andWhere('product.cuvee = TRUE')
                   ->andWhere('product.position < :position')
                   ->addOrderBy('product.position', 'DESC')
                   ->setMaxResults(1)
                   ->setParameter('position', $position)
                   ->getQuery();

        return $qb->getOneOrNullResult();
    }
}
