<?php

namespace App\Tests\Service;

use App\Entity\User;
use App\Exception\UserAlreadyExistsException;
use App\Repository\UserRepository;
use App\Service\UserManagementService;
use Doctrine\ORM\EntityManagerInterface;
use PHPUnit\Framework\TestCase;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;

class UserManagementServiceTest extends TestCase
{
    private UserRepository $userRepository;
    private EntityManagerInterface $em;
    private UserPasswordHasherInterface $passwordHasher;
    private UserManagementService $service;

    protected function setUp(): void
    {
        $this->userRepository = $this->createStub(UserRepository::class);
        $this->em = $this->createStub(EntityManagerInterface::class);
        $this->passwordHasher = $this->createStub(UserPasswordHasherInterface::class);

        $this->service = new UserManagementService(
            $this->userRepository,
            $this->em,
            $this->passwordHasher
        );
    }

    public function testCreateBaseUserSuccess(): void
    {
        $email = 'test@example.com';
        $firstName = 'John';
        $lastName = 'Doe';
        $roles = ['ROLE_USER'];

        $userRepository = $this->createStub(UserRepository::class);
        $userRepository->method('findOneBy')->willReturn(null);

        $passwordHasher = $this->createStub(UserPasswordHasherInterface::class);
        $passwordHasher->method('hashPassword')->willReturn('hashed_password');

        $em = $this->createMock(EntityManagerInterface::class);
        $em->expects($this->once())
            ->method('persist')
            ->with($this->isInstanceOf(User::class));

        $service = new UserManagementService($userRepository, $em, $passwordHasher);
        $user = $service->createBaseUser($email, $firstName, $lastName, $roles);

        $this->assertEquals($email, $user->getEmail());
        $this->assertEquals($firstName, $user->getFirstName());
        $this->assertEquals($lastName, $user->getLastName());
        $this->assertEquals($roles, $user->getRoles());
        $this->assertEquals('hashed_password', $user->getPassword());
        $this->assertNotEmpty($user->getTempPassword());
    }

    public function testCreateBaseUserThrowsExceptionIfUserExists(): void
    {
        $email = 'existing@example.com';
        
        $userRepository = $this->createStub(UserRepository::class);
        $userRepository->method('findOneBy')->willReturn(new User());

        $service = new UserManagementService($userRepository, $this->em, $this->passwordHasher);

        $this->expectException(UserAlreadyExistsException::class);

        $service->createBaseUser($email, 'John', 'Doe', []);
    }

    public function testCreateBaseUserThrowsExceptionIfInvalidData(): void
    {
        $this->expectException(\InvalidArgumentException::class);
        $this->service->createBaseUser('', 'John', 'Doe', []);
    }
}
