<?php

namespace App\Repository;

use Doctrine\ORM\EntityRepository;
use Doctrine\Common\Collections\ArrayCollection;

class AlertRepository extends EntityRepository
{
    // getOnlineAlert
    public function getOnlineAlert(array $roles = [], string $order = 'ASC'): array
    {
        if (!in_array($order, ['ASC', 'DESC'], true)) {
            throw new \UnexpectedValueException('Wrong order: ' . $order);
        }

        $qb = $this->createQueryBuilder('a');
        $qb->join('a.roles', 'r');

        if (count($roles)) {
            $ids = [];

            foreach ($roles as $r) {
                $ids[] = (int) $r->getId();
            }

            $qb->andWhere($qb->expr()->in('r.id', $ids));
        }

        $qb->andWhere('a.publishedat <= :today')
          ->andWhere($qb->expr()->orX(
              $qb->expr()->gt('a.unpublishedat', ':today'),
              $qb->expr()->isNull('a.unpublishedat')
          ))
          ->orderBy('a.rowOrder', $order);

        return $qb->getQuery()
            ->setParameter('today', date('Y-m-d'))
            ->getResult()
        ;
    }

    public function getUserAlerts($user,$idalertcategory,$alertcategoryfilter,$ssoitems) {
        // Profilage
        $roles=($user?$user->getRoles():["ROLE_ANONYME"]);
        $niveau01=($user?$user->getNiveau01():null);
        $groups=($user?$user->getGroups():[]);

        $userreads=($user?$user->getAlertreaders():new ArrayCollection());

        // Initialisation du calcul des alerts
        $alerts=new ArrayCollection();

        // Récupération des alerts par rôles
        foreach($roles as $role) {
            $qb = $this->createQueryBuilder('a');
            $qb->select('alert')
                ->from("App\Entity\Alert", 'alert')
                ->where($qb->expr()->like('alert.roles', $qb->expr()->literal("%$role%")))
                ->andWhere('alert.publishedat <= :today')
                ->andWhere($qb->expr()->orX(
                    $qb->expr()->gt('alert.unpublishedat', ':today'),
                    $qb->expr()->isNull('alert.unpublishedat')
                ))    
                ->setParameter('today', date('Y-m-d'));            
            
            if($idalertcategory && $alertcategoryfilter) {
                $qb->andWhere("alert.alertcategory=:alertcategory")
                    ->setParameter("alertcategory",$alertcategoryfilter);
            }
            $alertsroles=$qb->getQuery()->getResult();

            foreach($alertsroles as $alertrole) {
                if(!$alerts->contains($alertrole)&&!$userreads->contains($alertrole)) $alerts->add($alertrole);
            }
        }

        // Récupération par Niveau01
        $qb = $this->createQueryBuilder('a');
        $qb->select('alert')
            ->from("App\Entity\Alert", 'alert')
            ->where(":niveau01 MEMBER OF alert.niveau01s")
            ->andWhere('alert.publishedat <= :today')
            ->andWhere($qb->expr()->orX(
                $qb->expr()->gt('alert.unpublishedat', ':today'),
                $qb->expr()->isNull('alert.unpublishedat')
            ))
            ->setParameter("niveau01",$niveau01)
            ->setParameter('today', date('Y-m-d'));
        
        if($idalertcategory && $alertcategoryfilter) {
            $qb->andWhere("alert.alertcategory=:alertcategory")
                ->setParameter("alertcategory",$alertcategoryfilter);
        }
        $alertsniveau01s=$qb->getQuery()->getResult();
        foreach($alertsniveau01s as $alertniveau01) {
            if(!$alerts->contains($alertniveau01)&&!$userreads->contains($alertniveau01)) $alerts->add($alertniveau01);
        }

        // Récupération des alerts par group
        foreach($groups as $group) {
            $qb = $this->createQueryBuilder('a');
            $qb->select('alert')
                ->from("App\Entity\Alert", 'alert')
                ->where(":group MEMBER OF alert.groups")
                ->andWhere('alert.publishedat <= :today')
                ->andWhere($qb->expr()->orX(
                    $qb->expr()->gt('alert.unpublishedat', ':today'),
                    $qb->expr()->isNull('alert.unpublishedat')
                ))
                ->setParameter("group",$group->getGroup())
                ->setParameter('today', date('Y-m-d'));
            
            if($idalertcategory && $alertcategoryfilter) {
                $qb->andWhere("alert.alertcategory=:alertcategory")
                    ->setParameter("alertcategory",$alertcategoryfilter);
            }
            $alertsgroups=$qb->getQuery()->getResult();
            foreach($alertsgroups as $alertgroup) {             
                if(!$alerts->contains($alertgroup)&&!$userreads->contains($alertgroup)) $alerts->add($alertgroup);
            }
        }

        // Récupération des alerts par item
        $bookmarks=null;
        $items=null;
        $itemcategorys=null;
        $this->getEntityManager()->getRepository("App\Entity\Item")->getUserItems($user,$bookmarks,$items,$itemcategorys,null,$ssoitems,4);
        foreach($items as $item) {
            $qb = $this->createQueryBuilder('a');
            $qb->select('alert')
                ->from("App\Entity\Alert", 'alert')
                ->where(":item MEMBER OF alert.items")
                ->andWhere('alert.publishedat <= :today')
                ->andWhere($qb->expr()->orX(
                    $qb->expr()->gt('alert.unpublishedat', ':today'),
                    $qb->expr()->isNull('alert.unpublishedat')
                ))
                ->setParameter("item",$item)
                ->setParameter('today', date('Y-m-d'));
            
            if($idalertcategory && $alertcategoryfilter) {
                $qb->andWhere("alert.alertcategory=:alertcategory")
                    ->setParameter("alertcategory",$alertcategoryfilter);
            }
            $alertsitems=$qb->getQuery()->getResult();
            foreach($alertsitems as $alertitem) {               
                if(!$alerts->contains($alertitem)&&!$userreads->contains($alertitem)) $alerts->add($alertitem);
            }
        }

        // Trie des alerts
        $alertsordered = $alerts->getIterator();
        $alertsordered->uasort(function ($first, $second) {
            return (int) $first->getRowOrder() > (int) $second->getRowOrder() ? 1 : -1;
        });

        return $alertsordered;
    }
}
