<?php

namespace App\Service;

use App\Entity\PasswordToken;
use App\Entity\User;
use Cake\Chronos\Chronos;
use Doctrine\ORM\EntityNotFoundException;

final class PasswordTokenService
{
    /**
     * @var PasswordTokenRepositoryInterface
     */
    private $repository;

    /**
     * PasswordTokenService constructor.
     *
     * @param PasswordTokenRepositoryInterface $repository
     */
    public function __construct(PasswordTokenRepositoryInterface $repository)
    {
        $this->repository = $repository;
    }

    /**
     * @param int $id
     *
     * @return PasswordToken
     *
     * @throws EntityNotFoundException
     */
    public function get(int $id): PasswordToken
    {
        $passwordToken = $this->repository->findById($id);
        if (!$passwordToken) {
            throw new EntityNotFoundException('PasswordToken with id '.$id.' does not exist!');
        }

        return $passwordToken;
    }

    /**
     * @return array|null
     */
    public function getAll(): ?array
    {
        return $this->repository->findAll();
    }

    /**
     * @param PasswordToken $passwordToken
     *
     * @return PasswordToken
     */
    public function save(PasswordToken $passwordToken): PasswordToken
    {
        $this->repository->save($passwordToken);

        return $passwordToken;
    }

    /**
     * @param PasswordToken $passwordToken
     */
    public function delete(PasswordToken $passwordToken): void
    {
        $this->repository->delete($passwordToken);
    }

    /**
     * @param string $token
     *
     * @return PasswordToken
     *
     * @throws EntityNotFoundException
     * @throws \Exception
     */
    public function getByToken(string $token): PasswordToken
    {
        /** @var PasswordToken $passwordToken */
        $passwordToken = $this->repository->findOneBy(['token' => $token]);

        if (null === $passwordToken) {
            throw new EntityNotFoundException('Token is invalid');
        }

        if ($passwordToken->getExpiresAt() < Chronos::create()) {
            throw new \Exception('Link has expired. Try again to reset your password');
        }

        return $passwordToken;
    }

    public function deleteByUser(User $user): void
    {
        $tokens = $this->repository->findBy(['user' => $user]);
        foreach ($tokens as $token) {
            $this->delete($token);
        }
    }
}
