 
import { chromium, FullConfig } from '@playwright/test';
import { TEST_CONFIG } from './utils/test-helpers';

// Load test user credentials from environment or use defaults
const getTestUser = () => {
  const email = process.env.TEST_EMAIL || 'e2e@test.com';
  const password = process.env.TEST_PASSWORD || 'Xk9$mP2#vL7@nQ4!wR8';
  return { email, password };
};

/**
 * Global Setup for Playwright E2E Tests
 * 
 * This setup runs ONCE before all tests to:
 * 1. Log in as a test user
 * 2. Save the authenticated session state to storageState.json
 * 3. All subsequent tests will use this saved state (no need to login again)
 * 
 * This eliminates:
 * - Rate limiting issues (only 1 login instead of N logins)
 * - Test execution time (no login overhead per test)
 * - Flaky authentication failures
 */

async function globalSetup(config: FullConfig) {
  console.log('🔧 [GLOBAL SETUP] Starting global setup...');

  const testUser = getTestUser();
  console.log(`🔧 [GLOBAL SETUP] Using test user: ${testUser.email}`);

  // Use the first project's browser (usually chromium)
  // Use the first project's browser (usually chromium)
  const browser = await chromium.launch({
    headless: true,
  });

  const context = await browser.newContext();
  const page = await context.newPage();

  try {
    // Step 1: Verify API is available before attempting login
    console.log('🔧 [GLOBAL SETUP] Verifying API availability...');
    console.log(`🔧 [GLOBAL SETUP] API URL: ${TEST_CONFIG.API_URL}`);

    const healthCheckResult = await page.evaluate(async ({ apiUrl }) => {
      try {
        // Remove /api/v1 from URL for health check (health is usually at root)
        const baseUrl = apiUrl.replace('/api/v1', '');
        const healthUrl = `${baseUrl}/health`;
        console.log(`[BROWSER] Health check: ${healthUrl}`);
        const healthResponse = await fetch(healthUrl, {
          method: 'GET',
          headers: { 'Content-Type': 'application/json' },
          // eslint-disable-next-line no-undef
          signal: AbortSignal.timeout(10000), // 10s timeout
        });
        return { success: healthResponse.ok, status: healthResponse.status };
      } catch (error) {
        return { success: false, error: error instanceof Error ? error.message : String(error) };
      }
    }, { apiUrl: TEST_CONFIG.API_URL });

    if (!healthCheckResult.success) {
      console.warn(`⚠️ [GLOBAL SETUP] API health check failed: ${healthCheckResult.error || `Status ${healthCheckResult.status}`}`);
      console.warn(`⚠️ [GLOBAL SETUP] Continuing anyway - API might be starting up...`);
    } else {
      console.log('✅ [GLOBAL SETUP] API is available');
    }

    // Navigate to frontend root (not /login to avoid routing issues)
    console.log('🔧 [GLOBAL SETUP] Navigating to frontend...');
    await page.goto(TEST_CONFIG.FRONTEND_URL, {
      waitUntil: 'domcontentloaded',
      timeout: 30000,
    });

    // Login via API directly in the browser context
    console.log('🔧 [GLOBAL SETUP] Attempting API login via browser...');
    const loginResult = await page.evaluate(async ({ apiUrl, email, password }) => {
      try {
        console.log(`[BROWSER] Attempting login to: ${apiUrl}/auth/login`);
        // eslint-disable-next-line no-undef
        const controller = new AbortController();
        const timeoutId = setTimeout(() => controller.abort(), 30000); // 30s timeout

        const response = await fetch(`${apiUrl}/auth/login`, {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
          },
          body: JSON.stringify({
            email,
            password,
          }),
          signal: controller.signal,
        });

        clearTimeout(timeoutId);

        if (!response.ok) {
          const errorText = await response.text();
          return { success: false, error: `HTTP ${response.status}: ${errorText}` };
        }

        const data = await response.json();
        const accessToken = data?.token?.access_token || data?.data?.token?.access_token || data?.access_token;
        const refreshToken = data?.token?.refresh_token || data?.data?.token?.refresh_token || data?.refresh_token;

        if (!accessToken) {
          return { success: false, error: 'No access token in response', data };
        }

        // Store tokens in localStorage
        localStorage.setItem('veza_access_token', accessToken);
        if (refreshToken) {
          localStorage.setItem('veza_refresh_token', refreshToken);
        }

        // Also set auth-storage for Zustand
        const authStorage = {
          state: {
            isAuthenticated: true,
            accessToken,
            refreshToken,
          },
        };
        localStorage.setItem('auth-storage', JSON.stringify(authStorage));

        return { success: true, accessToken, refreshToken };
      } catch (error) {
        const errorMessage = error instanceof Error ? error.message : String(error);
        console.error(`[BROWSER] Login error: ${errorMessage}`);
        // Check if it's a network error
        if (errorMessage.includes('Failed to fetch') || errorMessage.includes('NetworkError') || errorMessage.includes('aborted')) {
          return { success: false, error: `Network error: ${errorMessage}. Is the API running at ${apiUrl}?` };
        }
        return { success: false, error: errorMessage };
      }
    }, { apiUrl: TEST_CONFIG.API_URL, email: testUser.email, password: testUser.password });

    if (!loginResult.success) {
      const errorMsg = loginResult.error || 'Unknown error';
      console.error(`❌ [GLOBAL SETUP] API login failed: ${errorMsg}`);
      console.error(`❌ [GLOBAL SETUP] Make sure:`);
      console.error(`   - Backend API is running at ${TEST_CONFIG.API_URL}`);
      console.error(`   - Test user exists: ${testUser.email}`);
      console.error(`   - CORS is configured correctly`);
      throw new Error(`API login failed: ${errorMsg}`);
    }

    console.log('✅ [GLOBAL SETUP] API login successful!');
    console.log(`✅ [GLOBAL SETUP] Access token: ${loginResult.accessToken?.substring(0, 20)}...`);

    // Verify tokens are stored
    const storedToken = await page.evaluate(() => localStorage.getItem('veza_access_token'));
    if (!storedToken) {
      throw new Error('Token not stored in localStorage');
    }

    // Save the authenticated state
    const storageStatePath = config.projects[0]?.use?.storageState as string || 'e2e/.auth/user.json';
    console.log(`💾 [GLOBAL SETUP] Saving authenticated state to: ${storageStatePath}`);
    await context.storageState({ path: storageStatePath });

    console.log('✅ [GLOBAL SETUP] Global setup completed successfully!');
  } catch (error) {
    console.error('❌ [GLOBAL SETUP] Global setup failed:', error);
    throw error;
  } finally {
    await browser.close();
  }
}

export default globalSetup;






