<?php

namespace AutoAdmin\Bundle\Admin\Service;

use AutoAdmin\Bundle\Admin\Entity\Administrator;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Exception\ORMException;
use Doctrine\ORM\OptimisticLockException;
use Exception;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;

class AdministratorManager
{
    private EntityManagerInterface $em;
    private UserPasswordHasherInterface $hasher;

    public function __construct(
        EntityManagerInterface      $em,
        UserPasswordHasherInterface $hasher
    )
    {
        $this->em = $em;
        $this->hasher = $hasher;
    }

    /**
     * @throws Exception
     */
    public function create(string $username, string $email, string $plainPassword, array $roles, bool $enabled = false): Administrator
    {
        if ($this->checkAlreadyExist($username, $email)) {
            throw new Exception("The user has not been created. Email or username already exist for admin.");
        }

        $admin = new Administrator();
        $admin->setUsername($username);
        $admin->setEmail($email);
        $admin->setRoles($roles);
        $admin->setPassword($this->hasher->hashPassword($admin, $plainPassword));
        $admin->setEnabled($enabled);

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

        return $admin;
    }

    public function checkAlreadyExist(string $username, string $email = null): bool
    {
        $userRepo = $this->em->getRepository(Administrator::class);

        if ($userRepo->findOneBy(['username' => $username]) !== null) {
            return true;
        }

        if ($email !== null && $userRepo->findOneBy(['email' => $email]) !== null) {
            return true;
        }

        return false;
    }

    /**
     * @throws Exception
     * @throws ORMException
     * @throws OptimisticLockException
     */
    public function changePassword(string $username, string $plainPassword): Administrator
    {
        if (!$this->checkAlreadyExist($username)) {
            throw new Exception("The user was not found.");
        }

        /** @var Administrator $admin */
        $admin = $this->em->getRepository(Administrator::class)->findOneBy(['username' => $username]);
        $admin->setPassword($this->hasher->hashPassword($admin, $plainPassword));

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

        return $admin;
    }
}
