<?php

declare(strict_types=1);

/*
 * This file is part of the Ferienpass package.
 *
 * (c) Richard Henkenjohann <richard@ferienpass.online>
 *
 * For more information visit the project website <https://ferienpass.online>
 * or the documentation under <https://docs.ferienpass.online>.
 */

namespace Ferienpass\CoreBundle\Facade;

use Doctrine\DBAL\ArrayParameterType;
use Doctrine\ORM\Query\Expr\Join;
use Doctrine\ORM\QueryBuilder;
use Ferienpass\CoreBundle\Entity\Attendance;
use Ferienpass\CoreBundle\Entity\Edition;
use Ferienpass\CoreBundle\Message\CommitAttendances;
use Ferienpass\CoreBundle\Message\DecisionLetterDispatched;
use Ferienpass\CoreBundle\Repository\AttendanceRepository;

/**
 * A decision, also called "Zulassungsbescheid", is sent out for every attendance after the "lot" procedure.
 *
 * @deprecated
 */
class DecisionsFacade
{
    public function __construct(private readonly AttendanceRepository $attendances)
    {
    }

    /** @return Attendance[] */
    public function attendances(?Edition $edition = null): array
    {
        return $this->queryBuilder($edition)
             ->getQuery()
             ->getResult()
        ;
    }

    public function queryBuilder(?Edition $edition = null): QueryBuilder
    {
        $qb2 = $this->attendances->createQueryBuilder('a');

        // Subquery: Attendances being notified already
        $sub = $this->attendances->createQueryBuilder('a1')
            ->leftJoin('a1.messengerLogs', 'm', Join::WITH, $qb2->expr()->orX('m.message = :sendDecisionsMessage', 'm.message = :sendDecisionsMessage2'))
            ->andWhere('m IS NOT NULL')
            ->andWhere('m.createdAt > a1.modifiedAt')
            ->addGroupBy('a1.id')
        ;

        return $this->attendances->createQueryBuilder('a')
            ->innerJoin('a.participant', 'p')
            ->innerJoin('a.offer', 'o')
            ->innerJoin('o.edition', 'e')
            ->andWhere('o.edition = :edition')
            ->setParameter('edition', $edition)
            ->andWhere('a.stash IS NULL')
            ->andWhere('a.status NOT IN (:status)')
            ->setParameter('status', ['withdrawn', 'waiting'], ArrayParameterType::STRING)

            // Either the attendance was created during lot procedure, or we don't know (probably admin).
            // First-come attendances never need to be notified.
            ->leftJoin('a.task', 't', Join::WITH, "t.type = 'application_system'")
            ->andWhere($qb2->expr()->orX('t IS NULL', "t.applicationSystem = 'lot'"))

            // Most importantly: Attendances NOT being notified yet
            ->andWhere($qb2->expr()->notIn('a.id', $sub->getDQL()))
            ->setParameter('sendDecisionsMessage', CommitAttendances::class)
            // Legacy
            ->setParameter('sendDecisionsMessage2', DecisionLetterDispatched::class)
        ;
    }
}
