import { test } from 'tap';
import Fastify from 'fastify';
import app from '../../src/app';
import { MikroORM } from '@mikro-orm/core';
import mikroOrmConfig from '../../mikro-orm.config';
import { User } from '@/apps/_app/entities/user/_User';

test('User API', async (t) => {
    // Setup
    const fastify = Fastify();
    await fastify.register(app);
    const orm = await MikroORM.init(mikroOrmConfig);
    const em = orm.em.fork();

    // Cleanup function
    const cleanup = async () => {
        await fastify.close();
        await orm.close();
    };

    try {
        t.test('POST /api/v1/app/users', async (t) => {
            const response = await fastify.inject({
                method: 'POST',
                url: '/api/v1/app/users',
                payload: {
                    username: 'apitestuser',
                    password: 'testpass123',
                    email: 'api@example.com',
                    roleName: 'user'
                }
            });

            t.equal(response.statusCode, 201, 'should return 201 status code');
            const body = JSON.parse(response.payload);
            t.ok(body.id, 'should return user with id');
            t.equal(body.username, 'apitestuser', 'should create user with correct username');

            // Cleanup this test's user
            const user = await em.findOne(User, { username: 'apitestuser' });
            if (user) await em.removeAndFlush(user);
        });

        t.test('POST /api/v1/app/users/login', async (t) => {
            // First create a user
            await fastify.inject({
                method: 'POST',
                url: '/api/v1/app/users',
                payload: {
                    username: 'logintestuser',
                    password: 'testpass123',
                    email: 'login@example.com',
                    roleName: 'user'
                }
            });

            const response = await fastify.inject({
                method: 'POST',
                url: '/api/v1/app/users/login',
                payload: {
                    username: 'logintestuser',
                    password: 'testpass123'
                }
            });

            t.equal(response.statusCode, 200, 'should return 200 status code');
            const body = JSON.parse(response.payload);
            t.ok(body.token, 'should return JWT token');
            t.equal(body.message, 'Authentication successful', 'should return success message');

            // Test with invalid credentials
            const invalidResponse = await fastify.inject({
                method: 'POST',
                url: '/api/v1/app/users/login',
                payload: {
                    username: 'logintestuser',
                    password: 'wrongpassword'
                }
            });

            t.equal(invalidResponse.statusCode, 401, 'should return 401 for invalid credentials');

            // Cleanup this test's user
            const user = await em.findOne(User, { username: 'logintestuser' });
            if (user) await em.removeAndFlush(user);
        });

        t.test('GET /api/v1/app/users (requires auth)', async (t) => {
            // First create and login as a user
            await fastify.inject({
                method: 'POST',
                url: '/api/v1/app/users',
                payload: {
                    username: 'authtestuser',
                    password: 'testpass123',
                    email: 'auth@example.com',
                    roleName: 'user'
                }
            });

            const loginResponse = await fastify.inject({
                method: 'POST',
                url: '/api/v1/app/users/login',
                payload: {
                    username: 'authtestuser',
                    password: 'testpass123'
                }
            });

            const { token } = JSON.parse(loginResponse.payload);

            const response = await fastify.inject({
                method: 'GET',
                url: '/api/v1/app/users',
                headers: {
                    Authorization: `Bearer ${token}`
                }
            });

            t.equal(response.statusCode, 200, 'should return 200 with valid token');
            const body = JSON.parse(response.payload);
            t.ok(Array.isArray(body), 'should return array of users');

            // Test without token
            const noAuthResponse = await fastify.inject({
                method: 'GET',
                url: '/api/v1/app/users'
            });

            t.equal(noAuthResponse.statusCode, 401, 'should return 401 without token');

            // Cleanup this test's user
            const user = await em.findOne(User, { username: 'authtestuser' });
            if (user) await em.removeAndFlush(user);
        });
    } finally {
        // Ensure cleanup happens even if tests fail
        await cleanup();
    }
}); 