<?php

namespace UserBundle\Repository;

use AppBundle\Model\SortingOptions;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\Query\Expr\Join;
use Doctrine\ORM\QueryBuilder;
use UserBundle\Entity\Notification\Schedule\AbstractNotificationSchedule;
use UserBundle\Entity\Recipient\AbstractRecipient;
use UserBundle\Enum\NotificationTypeEnum;

/**
 * NotificationRepository
 *
 * This class was generated by the Doctrine ORM. Add your own custom
 * repository methods below.
 */
class NotificationSendHistoryRepository extends EntityRepository
{

    /**
     * @param integer $notification A Notification entity id.
     *
     * @return \Doctrine\ORM\QueryBuilder
     */
    public function getListForNotification($notification)
    {
        return $this->createQueryBuilder('History')
            ->select('History.date')
            ->where('History.notification = :notification')
            ->setParameter('notification', $notification);
    }

    /**
     * @param AbstractRecipient $recipient      A AbstractRecipient entity instance.
     * @param SortingOptions    $sortingOptions A SortingOptions instance.
     * @param string            $typeFilter     Notification type filter.
     *
     * @return QueryBuilder
     */
    public function getListForRecipient(
        AbstractRecipient $recipient,
        SortingOptions $sortingOptions,
        $typeFilter
    ) {
        $qb = $this->createQueryBuilder('History')
            ->select(
                'partial History.{id, date}',
                'partial Notification.{id, name, notificationType}',
                'Schedule'
            )
            ->join('History.notification', 'Notification')
            ->join('History.schedules', 'Schedule')
            ->join('Notification.recipients', 'Recipient', Join::WITH, 'Recipient.id = :recipient')
            ->setParameter('recipient', $recipient->getId());

        $sortField = $sortingOptions->getFieldName();
        switch ($sortField) {
            case 'name':
                $sortField = 'Notification.name';
                break;

            case 'type':
                $sortField = 'Notification.notificationType';
                break;

            case 'scheduleTime':
                $countDql = $this->_em->createQueryBuilder()
                    ->select('COUNT(_Schedule.id)')
                    ->from(AbstractNotificationSchedule::class, '_Schedule')
                    ->where('_Schedule.history = History.id')
                    ->getDQL();

                $qb->addSelect("($countDql) AS HIDDEN scheduleCount");
                $sortField = 'scheduleCount';
                break;

            case 'sentTime':
                $sortField = 'History.date';
                break;

            default:
                throw new \InvalidArgumentException("Unknown field name '{$sortField}'.");
        }

        switch ($typeFilter) {
            case NotificationTypeEnum::ALERT:
                $qb
                    ->andWhere('Notification.notificationType = :type')
                    ->setParameter('type', NotificationTypeEnum::ALERT);
                break;

            case NotificationTypeEnum::NEWSLETTER:
                $qb
                    ->andWhere('Notification.notificationType = :type')
                    ->setParameter('type', NotificationTypeEnum::NEWSLETTER);
                break;
        }

        return $qb->orderBy($sortField, $sortingOptions->getSortDirection());
    }
}
