<?php

declare(strict_types=1);

namespace App\Administration\Application\Command\ArchiveClass;

use App\Administration\Application\Query\HasStudentsInClass\HasStudentsInClassQuery;
use App\Administration\Domain\Exception\ClasseNonSupprimableException;
use App\Administration\Domain\Model\SchoolClass\ClassId;
use App\Administration\Domain\Model\SchoolClass\SchoolClass;
use App\Administration\Domain\Repository\ClassRepository;
use App\Shared\Domain\Clock;
use Symfony\Component\Messenger\Attribute\AsMessageHandler;
use Symfony\Component\Messenger\MessageBusInterface;
use Symfony\Component\Messenger\Stamp\HandledStamp;

/**
 * Handler pour archiver (soft delete) une classe scolaire.
 *
 * Vérifie qu'aucun élève n'est affecté à la classe avant de permettre l'archivage.
 */
#[AsMessageHandler(bus: 'command.bus')]
final readonly class ArchiveClassHandler
{
    public function __construct(
        private ClassRepository $classRepository,
        private MessageBusInterface $queryBus,
        private Clock $clock,
    ) {
    }

    public function __invoke(ArchiveClassCommand $command): SchoolClass
    {
        $classId = ClassId::fromString($command->classId);
        $class = $this->classRepository->get($classId);

        // Vérifier s'il y a des élèves affectés
        $envelope = $this->queryBus->dispatch(new HasStudentsInClassQuery($command->classId));
        /** @var HandledStamp|null $handledStamp */
        $handledStamp = $envelope->last(HandledStamp::class);

        if ($handledStamp !== null) {
            /** @var int $studentCount */
            $studentCount = $handledStamp->getResult();

            if ($studentCount > 0) {
                throw ClasseNonSupprimableException::carElevesAffectes($classId, $studentCount);
            }
        }

        $class->archiver($this->clock->now());

        $this->classRepository->save($class);

        return $class;
    }
}
