import { test } from 'tap';
import { MikroORM } from '@mikro-orm/core';
import { UserService } from '@/apps/_app/services/UserService';
import { UserRepository } from '@/apps/_app/repositories/UserRepository';
import { UserRoleRepository } from '@/apps/_app/repositories/UserRoleRepository';
import { User } from '@/apps/_app/entities/user/_User';
import { UserRole } from '@/apps/_app/entities/user/UserRole';
import mikroOrmConfig from '../../mikro-orm.config';

test('UserService', async (t) => {
    // Setup
    const orm = await MikroORM.init(mikroOrmConfig);
    const em = orm.em.fork();

    const userRepository = new UserRepository(em, User);
    const userRoleRepository = new UserRoleRepository(em, UserRole);
    const userService = new UserService(em, userRepository, userRoleRepository);

    t.test('createUserWithRole', async (t) => {
        const username = 'testuser';
        const password = 'testpass123';
        const email = 'test@example.com';
        const roleName = 'user';

        const user = await userService.createUserWithRole(username, password, email, roleName);

        t.ok(user, 'should create a user');
        t.equal(user.username, username, 'should set correct username');
        t.equal(user.email, email, 'should set correct email');
        t.ok(user.roles.length > 0, 'should assign roles');
        t.equal(user.roles[0].name, roleName, 'should assign correct role');

        // Cleanup
        await em.removeAndFlush(user);
    });

    t.test('authenticateUser', async (t) => {
        const username = 'authuser';
        const password = 'authpass123';
        const email = 'auth@example.com';
        const roleName = 'user';

        // Create a user first
        const user = await userService.createUserWithRole(username, password, email, roleName);

        t.test('with valid credentials', async (t) => {
            const authenticatedUser = await userService.authenticateUser(username, password);
            t.ok(authenticatedUser, 'should authenticate successfully');
            t.equal(authenticatedUser.username, username, 'should return correct user');
        });

        t.test('with invalid password', async (t) => {
            try {
                await userService.authenticateUser(username, 'wrongpassword');
                t.fail('should throw error for invalid password');
            } catch (error) {
                t.ok(error, 'should throw error');
            }
        });

        t.test('with non-existent user', async (t) => {
            try {
                await userService.authenticateUser('nonexistent', password);
                t.fail('should throw error for non-existent user');
            } catch (error) {
                t.ok(error, 'should throw error');
            }
        });

        // Cleanup
        await em.removeAndFlush(user);
    });

    // Cleanup
    await orm.close();
}); 