<?php

declare(strict_types=1);

namespace CpCreation\VitiCore\Bridge\Symfony\Bundle\Security;

use CpCreation\VitiCore\Bridge\Symfony\Bundle\Utils\Mailer;
use CpCreation\VitiCore\User\Model\User;
use CpCreation\VitiCore\User\Repository\UserRepository;

final class PasswordResetService
{
    private const EXPIRATION_INTERVAL = '+15 minutes';
    private const RESEND_COOLDOWN = '-5 minutes';

    public function __construct(
        private readonly UserRepository $userRepository,
        private readonly Mailer $mailer,
    ) {
    }

    public function sendResetEmail(User $user, bool $force = false, string $resetRoute = 'app_reset_password'): bool
    {
        if (!$force && !$this->canResend($user)) {
            return false;
        }

        $now = new \DateTimeImmutable();
        $user->setResetPasswordToken(bin2hex(random_bytes(32)));
        $user->setResetPasswordRequestedAt($now);
        $user->setResetPasswordExpiresAt($now->modify(self::EXPIRATION_INTERVAL));
        $this->userRepository->save($user);
        $this->mailer->sendPasswordReset($user, $resetRoute);

        return true;
    }

    public function canResend(User $user): bool
    {
        $requestedAt = $user->getResetPasswordRequestedAt();

        if (null === $requestedAt) {
            return true;
        }

        return $requestedAt <= new \DateTimeImmutable(self::RESEND_COOLDOWN);
    }

    public function isExpired(User $user): bool
    {
        $expiresAt = $user->getResetPasswordExpiresAt();

        return null === $expiresAt || $expiresAt < new \DateTimeImmutable();
    }

    public function clear(User $user): void
    {
        $user->setResetPasswordToken(null);
        $user->setResetPasswordRequestedAt(null);
        $user->setResetPasswordExpiresAt(null);
        $this->userRepository->save($user);
    }
}
