<?php

namespace AutoAdmin\Bundle\Admin\Security;

use AutoAdmin\Bundle\Admin\Model\AdministratorInterface;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use Symfony\Component\Security\Core\Exception\UserNotFoundException;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;

class AdministratorProvider implements UserProviderInterface
{
    public function __construct(
        protected EntityManagerInterface $em,
    ) {
    }

    public function loadUserByUsername($username)
    {
        return $this->fetchUser($username);
    }

    public function refreshUser(UserInterface $user)
    {
        if (!$user instanceof AdministratorInterface) {
            throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', get_class($user)));
        }

        $username = $user->getUsername();

        return $this->fetchUser($username);
    }

    public function supportsClass($class)
    {
        $refl = new \ReflectionClass($class);

        return AdministratorInterface::class === $class || $refl->isSubclassOf(AdministratorInterface::class);
    }

    private function fetchUser($username)
    {
        $repo = $this->em->getRepository(AdministratorInterface::class);

        $found = $repo->findOneBy(['username' => $username]);
        if (empty($found)) {
            $found = $repo->findOneBy(['email' => $username]);
        }

        return $found;
    }

    public function loadUserByIdentifier(string $identifier): UserInterface
    {
        $repo = $this->em->getRepository(AdministratorInterface::class);

        $found = $repo->findOneBy(['username' => $identifier]);
        if (empty($found)) {
            $found = $repo->findOneBy(['email' => $identifier]);
        }

        if ($found) {
            return $found;
        }

        throw new UserNotFoundException();
    }
}
