<?php

namespace App\User\Action\Handler;

use App\User\Action\Command\RegisterLdapUserCommand;
use App\User\Action\Result\RegisterLdapUserResult;
use App\User\Framework\Entity\User;
use App\User\Framework\Entity\UserPreference;
use App\User\Framework\Repository\PreferencesRepository;
use App\User\Framework\Repository\UserRepository;
use Doctrine\ORM\EntityManagerInterface;
use OneToMany\RichBundle\Contract\CommandInterface as C;
use OneToMany\RichBundle\Contract\HandlerInterface;
use OneToMany\RichBundle\Contract\ResultInterface as R;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;

/** @implements HandlerInterface<RegisterLdapUserCommand, RegisterLdapUserResult> */
class RegisterLdapUserHandler implements HandlerInterface
{
    public function __construct(
        private readonly EntityManagerInterface $entityManager,
        private readonly PreferencesRepository $preferenceRepository,
        private readonly UserPasswordHasherInterface $userPasswordHasher,
        private readonly UserRepository $userRepository,
    ) {}

    public function handle(C $command): R
    {
        $user = $this->userRepository->findOneBy(['username' => $command->username]);
        if (null === $user) {
            $user = new User();
            $user->setPassword($this->userPasswordHasher->hashPassword($user, $command->password));
        }

        $user->setUsername($command->username);
        $user->setEmail($command->email);
        $user->setName($command->name);
        $this->entityManager->persist($user);
        $this->entityManager->flush();

        $this->setUserPreferences($user, $this->preferenceRepository->findEnabled());
        $this->entityManager->flush();

        return new RegisterLdapUserResult($user);
    }

    private function setUserPreferences(User $user, array $preferences): void
    {
        foreach ($preferences as $preference) {
            $user->addUserPreference((new UserPreference())
                ->setUser($user)
                ->setPreference($preference)
                ->setPreferenceValue(null)
            );
        }
    }
}
