<?php

declare(strict_types=1);

namespace App\Administration\Application\Command\ActivateParentInvitation;

use App\Administration\Application\Port\PasswordHasher;
use App\Administration\Domain\Exception\ParentInvitationNotFoundException;
use App\Administration\Domain\Model\Invitation\InvitationCode;
use App\Administration\Domain\Repository\ParentInvitationRepository;
use App\Shared\Domain\Clock;
use Symfony\Component\Messenger\Attribute\AsMessageHandler;

#[AsMessageHandler(bus: 'command.bus')]
final readonly class ActivateParentInvitationHandler
{
    public function __construct(
        private ParentInvitationRepository $invitationRepository,
        private PasswordHasher $passwordHasher,
        private Clock $clock,
    ) {
    }

    /**
     * Validates the invitation code and prepares activation data.
     * Actual user creation, activation, and linking is done in the Processor.
     *
     * @throws ParentInvitationNotFoundException if code is invalid
     */
    public function __invoke(ActivateParentInvitationCommand $command): ActivateParentInvitationResult
    {
        $code = new InvitationCode($command->code);

        $invitation = $this->invitationRepository->findByCode($code);
        if ($invitation === null) {
            throw ParentInvitationNotFoundException::withCode($code);
        }

        $now = $this->clock->now();

        // Validate only - does not change state
        $invitation->validerPourActivation($now);

        $hashedPassword = $this->passwordHasher->hash($command->password);

        return new ActivateParentInvitationResult(
            invitationId: (string) $invitation->id,
            studentId: (string) $invitation->studentId,
            parentEmail: (string) $invitation->parentEmail,
            tenantId: $invitation->tenantId,
            hashedPassword: $hashedPassword,
            firstName: $command->firstName,
            lastName: $command->lastName,
        );
    }
}
