<?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 Export;

use Chill\MainBundle\Export\AccompanyingCourseExportHelper;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\PersonBundle\Entity\AccompanyingPeriod\ClosingMotive;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;

/**
 * @internal
 *
 * @coversNothing
 */
class AccompanyingCourseExportHelperTest extends KernelTestCase
{
    /**
     * @var list<array{0: class-string, 1: int}>
     */
    private static array $entitiesToDelete = [];

    private EntityManagerInterface $em;

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

    public static function tearDownAfterClass(): void
    {
        self::bootKernel();
        $em = self::getContainer()->get(EntityManagerInterface::class);

        foreach (self::$entitiesToDelete as [$class, $id]) {
            $entity = $em->find($class, $id);

            if (null !== $entity) {
                $em->remove($entity);
            }
        }

        $em->flush();
    }

    public function testExclusionOnClosingMotive(): void
    {
        [$periodA, $periodB, $periodC] = $this->prepareData();

        $qb = $this->em->getRepository(AccompanyingPeriod::class)->createQueryBuilder('acp');
        AccompanyingCourseExportHelper::addClosingMotiveExclusionClause($qb);

        $qb->select('acp.id');

        $periodIdsFound = array_map(fn ($el) => $el['id'], $qb->getQuery()->getResult());

        $periodA = $this->em->find(AccompanyingPeriod::class, $periodA->getId());
        $periodB = $this->em->find(AccompanyingPeriod::class, $periodB->getId());
        $periodC = $this->em->find(AccompanyingPeriod::class, $periodC->getId());

        self::assertContains($periodA->getId(), $periodIdsFound, 'Period without canceled closing motive has been found');
        self::assertNotContains($periodB->getId(), $periodIdsFound, 'Period with canceled closing motive has not been found');
        self::assertNotContains($periodC->getId(), $periodIdsFound, 'Period with child canceled closing motive has not been found');
    }

    private function prepareData()
    {
        $cmA = new ClosingMotive();
        $cmA->setIsCanceledAccompanyingPeriod(false);

        $cmB = new ClosingMotive();
        $cmB->setIsCanceledAccompanyingPeriod(true);

        $cmChild = new ClosingMotive();
        $cmB->addChildren($cmChild);

        $this->em->persist($cmA);
        $this->em->persist($cmB);
        $this->em->persist($cmChild);

        $periodA = new AccompanyingPeriod();
        $periodB = new AccompanyingPeriod();
        $periodC = new AccompanyingPeriod();

        $periodA->setClosingMotive($cmA);
        $periodB->setClosingMotive($cmB);
        $periodC->setClosingMotive($cmChild);

        $this->em->persist($periodA);
        $this->em->persist($periodB);
        $this->em->persist($periodC);

        self::$entitiesToDelete[] = [AccompanyingPeriod::class, $periodA];
        self::$entitiesToDelete[] = [AccompanyingPeriod::class, $periodB];
        self::$entitiesToDelete[] = [AccompanyingPeriod::class, $periodC];
        self::$entitiesToDelete[] = [ClosingMotive::class, $cmChild];
        self::$entitiesToDelete[] = [ClosingMotive::class, $cmA];
        self::$entitiesToDelete[] = [ClosingMotive::class, $cmB];

        $this->em->flush();
        $this->em->clear();

        return [$periodA, $periodB, $periodC];
    }
}
