<?php

declare(strict_types=1);

namespace App\Repository;

use App\Entity\Notification;
use App\Entity\User;
use DateTimeImmutable;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;

/**
 * @extends ServiceEntityRepository<Notification>
 */
final class NotificationRepository extends ServiceEntityRepository
{
    public function __construct(ManagerRegistry $registry)
    {
        parent::__construct($registry, Notification::class);
    }

    /**
     * @return list<Notification>
     */
    public function findUnreadByRecipient(User $recipient): array
    {
        return $this->createQueryBuilder('n')
            ->andWhere('n.recipient = :recipient')
            ->andWhere('n.isRead = :isRead')
            ->setParameter('recipient', $recipient)
            ->setParameter('isRead', false)
            ->orderBy('n.createdAt', 'DESC')
            ->setMaxResults(50)
            ->getQuery()
            ->getResult()
        ;
    }

    /**
     * @return list<Notification>
     */
    public function findTodayByRecipient(User $recipient): array
    {
        $todayStart = new DateTimeImmutable('today 00:00:00');

        return $this->createQueryBuilder('n')
            ->andWhere('n.recipient = :recipient')
            ->andWhere('n.createdAt >= :todayStart')
            ->setParameter('recipient', $recipient)
            ->setParameter('todayStart', $todayStart)
            ->orderBy('n.createdAt', 'DESC')
            ->getQuery()
            ->getResult()
        ;
    }

    /**
     * @return list<Notification>
     */
    public function findLatestByRecipient(User $recipient, int $limit = 10): array
    {
        return $this->createQueryBuilder('n')
            ->andWhere('n.recipient = :recipient')
            ->setParameter('recipient', $recipient)
            ->orderBy('n.createdAt', 'DESC')
            ->setMaxResults($limit)
            ->getQuery()
            ->getResult()
        ;
    }

    public function markAllReadByRecipient(User $recipient): int
    {
        return $this->createQueryBuilder('n')
            ->update()
            ->set('n.isRead', ':isRead')
            ->andWhere('n.recipient = :recipient')
            ->andWhere('n.isRead = :current')
            ->setParameter('isRead', true)
            ->setParameter('current', false)
            ->setParameter('recipient', $recipient)
            ->getQuery()
            ->execute()
        ;
    }

    public function existsForRecipientCategoryTargetMessage(
        User $recipient,
        string $category,
        string $target,
        string $message,
    ): bool {
        $id = $this->createQueryBuilder('n')
            ->select('n.id')
            ->andWhere('n.recipient = :recipient')
            ->andWhere('n.category = :category')
            ->andWhere('n.target = :target')
            ->andWhere('n.message = :message')
            ->setParameter('recipient', $recipient)
            ->setParameter('category', $category)
            ->setParameter('target', $target)
            ->setParameter('message', $message)
            ->setMaxResults(1)
            ->getQuery()
            ->getOneOrNullResult()
        ;

        return null !== $id;
    }
}
