
import { test as base, expect } from '@playwright/test';
import { request } from '@playwright/test';
import { exec as cp_exec } from 'child_process';
import { promisify } from 'util';

const exec = promisify(cp_exec);

// Define the type for our custom fixtures
type MyFixtures = {
    createUniqueUser: () => Promise<{ email: string, password: string, id: string, token: string }>;
    createAdminUser: () => Promise<{ email: string, password: string, id: string, token: string }>;
};

// Extend the base test with our custom fixture
export const test = base.extend<MyFixtures>({
    createUniqueUser: async ({ }, use) => {
        const apiContext = await request.newContext({
            baseURL: 'http://127.0.0.1:3201' // Direct access to backend
        });

        // Setup: Helper function to create a user
        const createUser = async () => {
            const uniqueId = Math.random().toString(36).substring(7);
            const email = `test.user.${uniqueId}@example.com`;
            const password = 'StrongPassword123!';

            const response = await apiContext.post('/api/auth/register', {
                data: {
                    email,
                    password
                }
            });

            const body = await response.json();

            // If registration fails because we hit a collision (unlikely) or other error, fail the test
            if (!response.ok() || !body.success) {
                console.error(`REGISTRATION FAILED: ${response.status()} ${response.statusText()}`);
                console.error(`RESPONSE BODY: ${JSON.stringify(body, null, 2)}`);
                throw new Error(`Failed to register user: ${JSON.stringify(body)}`);
            }

            return { email, password, id: body.data.user.id, token: body.data.token };
        };

        // Use the fixture
        await use(createUser);
    },

    createAdminUser: async ({ createUniqueUser }, use) => {
        // Setup: Helper function to create an admin user (create regular -> promote)
        const createAdmin = async () => {
            const user = await createUniqueUser(); // Create a regular user first

            console.log(`Promoting user ${user.email} to ADMIN...`);
            try {
                const { stdout, stderr } = await exec(`npx ts-node promote_admin.ts ${user.email}`, {
                    cwd: 'server',
                    env: { ...process.env, APP_MODE: 'test', DATABASE_URL: 'file:d:/Coding/gymflow/server/prisma/test.db', DATABASE_URL_TEST: 'file:d:/Coding/gymflow/server/prisma/test.db' }
                });
                if (stderr) {
                    console.error(`Promote Admin Stderr: ${stderr}`);
                }
                console.log(`Promote Admin Stdout: ${stdout}`);
                if (!stdout.includes(`User ${user.email} promoted to ADMIN`)) {
                    throw new Error('Admin promotion failed or unexpected output.');
                }
            } catch (error: any) {
                console.error(`Error promoting user ${user.email} to ADMIN:`, error);
                if (error.stdout) console.log(`Failed CMD Stdout: ${error.stdout}`);
                if (error.stderr) console.error(`Failed CMD Stderr: ${error.stderr}`);
                throw error;
            }
            return user;
        };

        await use(createAdmin);
    },
});

export { expect };
