<?php

declare(strict_types=1);

/*
 * Chill is a software for social workers
 *
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */

namespace Chill\TicketBundle\Tests\Repository;

use Chill\MainBundle\Entity\Center;
use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Entity\UserGroup;
use Chill\PersonBundle\DataFixtures\Helper\RandomPersonHelperTrait;
use Chill\TicketBundle\Entity\EmergencyStatusEnum;
use Chill\TicketBundle\Entity\Motive;
use Chill\TicketBundle\Entity\StateEnum;
use Chill\TicketBundle\Repository\TicketACLAwareRepository;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;

/**
 * @internal
 *
 * @coversNothing
 */
class TicketACLAwareRepositoryTest extends KernelTestCase
{
    use RandomPersonHelperTrait;

    private TicketACLAwareRepository $repository;
    private EntityManagerInterface $entityManager;

    protected function setUp(): void
    {
        self::bootKernel();
        $this->entityManager = self::getContainer()->get(EntityManagerInterface::class);
        $this->repository = new TicketACLAwareRepository($this->entityManager);
    }

    public function testFindNoParameters(): void
    {
        // Test the findTickets method with byPerson parameter
        $actual = $this->repository->findTickets([]);

        // Only verify that the query executes successfully without checking results
        self::assertIsList($actual);
    }

    public function testFindTicketByPerson(): void
    {
        $person = $this->getRandomPerson($this->entityManager);

        // Test the findTickets method with byPerson parameter
        $actual = $this->repository->findTickets(['byPerson' => [$person]]);

        // Only verify that the query executes successfully without checking results
        self::assertIsList($actual);
    }

    public function testCountTicketsByPerson(): void
    {
        $person = $this->getRandomPerson($this->entityManager);

        $result = $this->repository->countTickets(['byPerson' => [$person]]);

        self::assertIsInt($result);
    }

    public function testCountTicketByCurrentStateSingleState(): void
    {
        $result = $this->repository->countTickets(['byCurrentState' => [StateEnum::OPEN]]);

        self::assertIsInt($result);
    }

    public function testFindTicketByCurrentStateMultipleState(): void
    {
        $result = $this->repository->findTickets(['byCurrentState' => [StateEnum::OPEN, StateEnum::CLOSED]]);

        self::assertIsArray($result);
    }

    public function testCountTicketByCurrentStateEmergencySingleState(): void
    {
        $result = $this->repository->countTickets(['byCurrentStateEmergency' => [EmergencyStatusEnum::YES]]);

        self::assertIsInt($result);
    }

    public function testFindTicketByCurrentStateEmergencyMultipleState(): void
    {
        $result = $this->repository->findTickets(['byCurrentStateEmergency' => [EmergencyStatusEnum::YES, EmergencyStatusEnum::NO]]);

        self::assertIsArray($result);
    }

    public function testFindTicketByMotives(): void
    {
        $motives = $this->entityManager->createQuery(sprintf('SELECT m FROM %s m', Motive::class))
            ->setMaxResults(2)
            ->getResult();

        if ([] === $motives) {
            throw new \UnexpectedValueException('No motives found');
        }

        $results = $this->repository->findTickets(['byMotives' => $motives]);

        self::assertIsArray($results);
    }

    public function testFindTicketByCreatedBefore(): void
    {
        $actual = $this->repository->findTickets(['byCreatedBefore' => (new \DateTimeImmutable('now'))->add(new \DateInterval('P1D'))]);

        self::assertIsArray($actual);
    }

    public function testFindTicketByCreatedAfter(): void
    {
        $actual = $this->repository->findTickets(['byCreatedAfter' => (new \DateTimeImmutable('now'))->sub(new \DateInterval('P1M'))]);

        self::assertIsArray($actual);
    }

    public function testFindByAddressee(): void
    {
        $users = $this->entityManager->createQuery('SELECT u FROM '.User::class.' u')
            ->setMaxResults(2)
            ->getResult();

        if ([] === $users) {
            throw new \UnexpectedValueException('No users found');
        }

        $actual = $this->repository->findTickets(['byAddressee' => $users]);

        self::assertIsArray($actual);
    }

    public function testFindByCreator(): void
    {
        $users = $this->entityManager->createQuery('SELECT u FROM '.User::class.' u')
            ->setMaxResults(2)
            ->getResult();

        if ([] === $users) {
            throw new \UnexpectedValueException('No users found');
        }

        $actual = $this->repository->findTickets(['byCreator' => $users]);

        self::assertIsArray($actual);
    }

    public function testCountByCreator(): void
    {
        $users = $this->entityManager->createQuery('SELECT u FROM '.User::class.' u')
            ->setMaxResults(2)
            ->getResult();

        if ([] === $users) {
            throw new \UnexpectedValueException('No users found');
        }

        $count = $this->repository->countTickets(['byCreator' => $users]);

        self::assertIsInt($count);
    }

    public function testFindByAddresseeGroup(): void
    {
        $userGroups = $this->entityManager->createQuery('SELECT ug FROM '.UserGroup::class.' ug')
            ->setMaxResults(2)
            ->getResult();

        if ([] === $userGroups) {
            throw new \UnexpectedValueException('No users found');
        }

        $actual = $this->repository->findTickets(['byCreator' => $userGroups]);

        self::assertIsArray($actual);
    }

    public function testFindByTicketid(): void
    {
        $actual = $this->repository->findTickets(['byTicketId' => 1]);

        self::assertIsArray($actual);
    }

    public function testFindByPersonCenter(): void
    {
        $centers = $this->entityManager->createQuery('SELECT c FROM '.Center::class.' c')
            ->setMaxResults(2)
            ->getResult();

        if ([] === $centers) {
            throw new \UnexpectedValueException('No centers found');
        }

        $actual = $this->repository->findTickets(['byPersonCenter' => $centers]);

        self::assertIsArray($actual);
    }
}
