<?php

namespace Lc\CaracoleBundle\Repository\Reduction;

use Doctrine\Common\Collections\ArrayCollection;
use Knp\Component\Pager\PaginatorInterface;
use Lc\CaracoleBundle\Model\Product\ProductFamilyInterface;
use Lc\CaracoleBundle\Repository\MerchantRepositoryQueryTrait;
use Lc\SovBundle\Model\User\UserInterface;
use Lc\SovBundle\Repository\AbstractRepositoryQuery;

class ReductionCatalogRepositoryQuery extends AbstractRepositoryQuery
{
    protected bool $isJoinProductFamilies = false;
    protected bool $isJoinProductFamily = false;
    protected bool $isJoinProductCategories = false;
    protected bool $isJoinUsers = false;
    protected bool $isJoinGroupUsers = false;

    use MerchantRepositoryQueryTrait;

    public function __construct(ReductionCatalogRepository $repository, PaginatorInterface $paginator)
    {
        parent::__construct($repository, 'r', $paginator);
    }

    public function joinUsers()
    {
        if (!$this->isJoinUsers) {
            $this->isJoinUsers = true;

            return $this
                ->leftJoin('.users', 'pf_users')
                ->addSelect('pf_users');
        }
        return $this;
    }

    public function joinGroupUsers()
    {
        if (!$this->isJoinGroupUsers) {
            $this->isJoinGroupUsers = true;

            return $this
                ->leftJoin('.groupUsers', 'groupUsers')
                ->addSelect('groupUsers');
        }
        return $this;
    }

    public function joinProductFamilies()
    {
        if (!$this->isJoinProductFamilies) {
            $this->isJoinProductFamilies = true;

            return $this
                ->leftJoin('.productFamilies', 'productFamilies')
                ->addSelect('productFamilies');
        }
        return $this;
    }

    public function joinProductFamily()
    {
        if (!$this->isJoinProductFamily) {
            $this->isJoinProductFamily = true;

            return $this
                ->leftJoin('.productFamily', 'productFamily')
                ->addSelect('productFamily');
        }

        return $this;
    }

    public function joinProductCategories()
    {
        if (!$this->isJoinProductCategories) {
            $this->isJoinProductCategories = true;

            return $this
                ->leftJoin('.productCategories', 'productCategories')
                ->addSelect('productCategories');
        }

        return $this;
    }

    public function filterProductFamily(ProductFamilyInterface $productFamily)
    {
        return $this
            ->andWhere('.productFamily = :productFamily')
            ->setParameter(':productFamily', $productFamily);
    }

    public function filterConditionDate()
    {
        return $this
            ->andWhere('.permanent = 1 OR ( .dateStart <= :now AND .dateEnd >= :now)')
            ->setParameter(':now', new \DateTime());
    }

    public function filterConditionUser(UserInterface $user = null)
    {
        $this->joinUsers();

        if ($user) {
            return $this
                ->andWhere(':user MEMBER OF .users OR .users is empty')
                ->setParameter('user', $user);
        } else {
            return $this
                ->andWhere('.users is empty');
        }
    }

    public function filterByUser(UserInterface $user = null)
    {
        return $this
            ->andWhere(':user MEMBER OF .users')
            ->setParameter('user', $user);

    }

    public function filterConditionGroupUser(UserInterface $user = null)
    {
        $this->joinGroupUsers();

        if ($user) {
            return $this
                ->andWhere(':groupUser MEMBER OF .groupUsers OR .groupUsers is empty')
                ->setParameter('groupUser', $user->getGroupUsers());
        } else {
            return $this
                ->andWhere('.groupUsers is empty');
        }
    }

    public function filterConditionProductFamilies(array $productFamiliesIds, array $productFamilies)
    {
        $this->joinProductFamilies();
        $this->joinProductFamily();

        return $this
            ->andWhere(':productFamiliesIds MEMBER OF .productFamilies OR .productFamilies is empty')
            ->andWhere('.productFamily IN (:productFamilies) OR .productFamily is null')
            ->setParameter('productFamiliesIds', $productFamiliesIds)
            ->setParameter('productFamilies', $productFamilies);
    }

    public function filterConditionProductFamily(ProductFamilyInterface $productFamily)
    {
        $this->joinProductFamily();

        return $this
            ->andWhere(':productFamily MEMBER OF .productFamily OR .productFamily is empty')
            ->setParameter('productFamily', $productFamily);
    }

    public function filterConditionProductCategories(array $productCategories)
    {
        $this->joinProductCategories();

        return $this
            ->andWhere(':productCategory MEMBER OF .productCategories OR .productCategories is empty')
            ->setParameter('productCategory', $productCategories);
    }

    public function filterIsNotLinkToProductFamily()
    {
        return $this->andWhere('.productFamily is null');
    }

}