<?php

declare(strict_types=1);

namespace App\Administration\Application\Command\CreateSubject;

use App\Administration\Domain\Exception\SubjectDejaExistanteException;
use App\Administration\Domain\Model\SchoolClass\SchoolId;
use App\Administration\Domain\Model\Subject\Subject;
use App\Administration\Domain\Model\Subject\SubjectCode;
use App\Administration\Domain\Model\Subject\SubjectColor;
use App\Administration\Domain\Model\Subject\SubjectName;
use App\Administration\Domain\Repository\SubjectRepository;
use App\Shared\Domain\Clock;
use App\Shared\Domain\Tenant\TenantId;

use function assert;

use Symfony\Component\Messenger\Attribute\AsMessageHandler;

/**
 * Handler pour créer une nouvelle matière.
 */
#[AsMessageHandler(bus: 'command.bus')]
final readonly class CreateSubjectHandler
{
    public function __construct(
        private SubjectRepository $subjectRepository,
        private Clock $clock,
    ) {
    }

    public function __invoke(CreateSubjectCommand $command): Subject
    {
        $tenantId = TenantId::fromString($command->tenantId);
        $schoolId = SchoolId::fromString($command->schoolId);

        // Value Objects validate input; assert non-empty for PHPStan
        assert($command->code !== '');
        assert($command->name !== '');
        $code = new SubjectCode($command->code);

        // Vérifier l'unicité du code dans le tenant et l'école
        $existingSubject = $this->subjectRepository->findByCode($code, $tenantId, $schoolId);
        if ($existingSubject !== null) {
            throw SubjectDejaExistanteException::avecCode($code);
        }

        $color = null;
        if ($command->color !== null) {
            assert($command->color !== '');
            $color = new SubjectColor($command->color);
        }

        $subject = Subject::creer(
            tenantId: $tenantId,
            schoolId: $schoolId,
            name: new SubjectName($command->name),
            code: $code,
            color: $color,
            createdAt: $this->clock->now(),
        );

        $this->subjectRepository->save($subject);

        return $subject;
    }
}
