<?php

declare(strict_types=1);

namespace App\Module\TimeTracking\Infrastructure\Doctrine;

use App\Module\TimeTracking\Domain\Entity\TimeEntry;
use App\Module\TimeTracking\Domain\Repository\TimeEntryRepositoryInterface;
use App\Shared\Domain\Contract\ProjectInterface;
use App\Shared\Domain\Contract\UserInterface;
use DateTimeImmutable;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;

/**
 * @extends ServiceEntityRepository<TimeEntry>
 */
class DoctrineTimeEntryRepository extends ServiceEntityRepository implements TimeEntryRepositoryInterface
{
    public function __construct(ManagerRegistry $registry)
    {
        parent::__construct($registry, TimeEntry::class);
    }

    public function findById(int $id): ?TimeEntry
    {
        return $this->find($id);
    }

    public function findActiveByUser(UserInterface $user): ?TimeEntry
    {
        return $this->findOneBy([
            'user'      => $user,
            'stoppedAt' => null,
        ]);
    }

    /**
     * @param null|UserInterface[]    $users
     * @param null|ProjectInterface[] $projects
     * @param null|int[]              $tagIds
     *
     * @return TimeEntry[]
     */
    public function findForExport(
        DateTimeImmutable $after,
        DateTimeImmutable $before,
        ?array $users = null,
        ?array $projects = null,
        ?array $tagIds = null,
    ): array {
        $qb = $this->createQueryBuilder('te')
            ->andWhere('te.startedAt >= :after')
            ->andWhere('te.startedAt < :before')
            ->setParameter('after', $after)
            ->setParameter('before', $before)
            ->orderBy('te.startedAt', 'ASC')
        ;

        if (null !== $users && [] !== $users) {
            $qb->andWhere('te.user IN (:users)')
                ->setParameter('users', $users)
            ;
        }

        if (null !== $projects && [] !== $projects) {
            $qb->andWhere('te.project IN (:projects)')
                ->setParameter('projects', $projects)
            ;
        }

        if (null !== $tagIds && [] !== $tagIds) {
            $qb->join('te.tags', 'tag')
                ->andWhere('tag.id IN (:tagIds)')
                ->setParameter('tagIds', $tagIds)
            ;
        }

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