<?php

declare(strict_types=1);

namespace CpCreation\VitiCore\Bridge\Symfony\Bundle\Mailer\Command;

use CpCreation\VitiCore\Bridge\Symfony\Bundle\Mailer\AbandonedCartReminderMailer;
use CpCreation\VitiCore\Bridge\Symfony\Bundle\Messenger\Messaging\CommandHandlerInterface;
use CpCreation\VitiCore\Marketing\Model\AbandonedCartReminder;
use CpCreation\VitiCore\Marketing\Repository\AbandonedCartConfigurationRepository;
use CpCreation\VitiCore\Marketing\Repository\AbandonedCartReminderRepository;
use Symfony\Component\Messenger\Attribute\AsMessageHandler;
use Symfony\Component\Messenger\Exception\UnrecoverableMessageHandlingException;

#[AsMessageHandler]
final readonly class AbandonedCartReminderMailCommandHandler implements CommandHandlerInterface
{
    public function __construct(
        private AbandonedCartReminderRepository $reminderRepository,
        private AbandonedCartConfigurationRepository $configurationRepository,
        private AbandonedCartReminderMailer $mailer,
    ) {}

    public function __invoke(AbandonedCartReminderMailCommand $command): void
    {
        $reminder = $this->reminderRepository->find($command->reminderId);
        if (!$reminder instanceof AbandonedCartReminder) {
            throw new UnrecoverableMessageHandlingException('Relance de panier abandonné introuvable.');
        }

        if (!hash_equals($reminder->getTokenHash(), hash('sha256', $command->token))) {
            throw new UnrecoverableMessageHandlingException('Jeton de relance de panier abandonné invalide.');
        }

        if (!$reminder->isScheduled()) {
            return;
        }

        $now = new \DateTimeImmutable();
        if ($reminder->getExpiresAt() <= $now) {
            $reminder->markExpired();
            $this->reminderRepository->save($reminder);

            return;
        }

        $configuration = $this->configurationRepository->findOne();
        if (
            null === $configuration
            || !$configuration->isEnabled()
            || !$reminder->getRule()->isEnabled()
            || !$reminder->getCart()->isAbandoned()
        ) {
            $reminder->cancel();
            $this->reminderRepository->save($reminder);

            return;
        }

        $this->mailer->send($reminder, $command->token);
        $reminder->markSent($now);
        $this->reminderRepository->save($reminder);
    }
}
