<?php

namespace AutoAdmin\Bundle\Admin\Service;

use AutoAdmin\Bundle\Admin\Mailer\AdminMailer;
use AutoAdmin\Bundle\Admin\Model\AdministratorInterface;
use DateTime;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Exception\ORMException;
use Doctrine\ORM\OptimisticLockException;
use Exception;
use Ramsey\Uuid\Uuid;
use Symfony\Component\HttpFoundation\Request;

class AdministratorResettingService
{
    const MAX_VALIDATE_TIME = '+2 days';

    private EntityManagerInterface $em;
    private AdministratorManager $adminService;
    private AdminMailer $adminMailer;

    public function __construct(
        EntityManagerInterface $em,
        AdministratorManager $adminService,
        AdminMailer $adminMailer
    ) {
        $this->em = $em;
        $this->adminService = $adminService;
        $this->adminMailer = $adminMailer;
    }

    /**
     * @throws Exception
     */
    public function request(Request $request): void
    {
        $email = $request->get('email');

        /** @var AdministratorInterface $admin */
        $admin = $this->em->getRepository(AdministratorInterface::class)->findOneBy(['email' => $email]);
        if (!$admin) {
            throw new Exception("L'utilisateur demandé n'existe pas");
        }

        $token = Uuid::uuid5(Uuid::NAMESPACE_URL, uniqid())->toString();
        $now = new DateTime();

        $admin->setPasswordRequestToken($token);
        $admin->setPasswordRequestAt($now);

        $this->em->persist($admin);
        $this->em->flush();

        $this->adminMailer->onForgetPassword($admin);
    }

    /**
     * @throws ORMException
     * @throws OptimisticLockException
     * @throws Exception
     */
    public function validate(AdministratorInterface $admin): bool|string
    {
        $maxValidation = $admin->getPasswordRequestAt();
        $maxValidation->modify(self::MAX_VALIDATE_TIME);

        if ($maxValidation <= new DateTime()) {
            return "Vous avez dépassé le délai maximal de réinitialisation du mot de passe, veuillez recommencer votre demande";
        }

        $admin = $this->adminService->changePassword($admin->getUsername(), $admin->getPassword());

        $admin->setPasswordRequestToken(null);
        $admin->setPasswordRequestAt(null);

        $this->em->persist($admin);
        $this->em->flush();

        return true;
    }
}
