import { test as base, Page } from '@playwright/test';
import { authenticateUser } from '../utils/authentication';
import * as path from 'path';
import * as fs from 'fs';

/**
 * Authenticated Fixture
 * 
 * Provides pre-authenticated browser state for tests
 * Mirrors Katalon's reusable login test case approach
 * 
 * Usage:
 *   import { test } from '../fixtures/authenticated.fixture';
 *   
 *   test('my test', async ({ authenticatedPage: page }) => {
 *     await page.goto('/shop');
 *     // Already authenticated!
 *   });
 */

const AUTH_STATE_PATH = path.join(process.cwd(), 'auth.json');

type AuthenticatedFixtures = {
  authenticatedPage: Page;
};

/**
 * Setup authentication and store state
 */
async function setupAuthentication(page: Page): Promise<boolean> {
  console.log('🔐 Setting up authentication...');
  
  try {
    // Attempt authentication
    const result = await authenticateUser(page);
    
    if (result.success) {
      console.log('✓ Authentication successful');
      
      // Save authentication state
      const context = page.context();
      await context.storageState({ path: AUTH_STATE_PATH });
      console.log('✓ Authentication state saved');
      
      return true;
    } else {
      console.error('❌ Authentication failed:', result.error);
      return false;
    }
  } catch (error) {
    console.error('❌ Authentication error:', error);
    return false;
  }
}

/**
 * Check if authentication state exists and is valid
 */
function hasAuthState(): boolean {
  return fs.existsSync(AUTH_STATE_PATH);
}

/**
 * Clear authentication state
 */
export function clearAuthState(): void {
  if (fs.existsSync(AUTH_STATE_PATH)) {
    fs.unlinkSync(AUTH_STATE_PATH);
    console.log('🗑️ Authentication state cleared');
  }
}

/**
 * Extended test with authenticated page fixture
 */
export const test = base.extend<AuthenticatedFixtures>({
  authenticatedPage: async ({ browser }, use) => {
    console.log('\n📋 Creating authenticated page...');
    
    // Check if we have existing auth state
    let context;
    
    if (hasAuthState()) {
      console.log('✓ Using existing authentication state');
      try {
        // Try to use existing authentication
        context = await browser.newContext({ storageState: AUTH_STATE_PATH });
        const page = await context.newPage();
        
        // Verify authentication is still valid
        await page.goto('/shop');
        await page.waitForTimeout(2000);
        
        // Check if we're redirected to login (auth expired)
        const currentUrl = page.url();
        if (currentUrl.includes('/login') || currentUrl === page.context().browser()?.contexts()[0]?.pages()[0]?.url()) {
          console.log('⚠ Authentication expired, re-authenticating...');
          await page.close();
          await context.close();
          clearAuthState();
          
          // Re-authenticate
          context = await browser.newContext();
          const newPage = await context.newPage();
          const success = await setupAuthentication(newPage);
          
          if (!success) {
            throw new Error('Failed to authenticate');
          }
          
          await use(newPage);
          await context.close();
          return;
        }
        
        // Authentication still valid
        console.log('✓ Authenticated page ready');
        await use(page);
        await context.close();
        return;
        
      } catch (error) {
        console.log('⚠ Error using existing auth state, re-authenticating...');
        if (context) {
          await context.close().catch(() => {});
        }
        clearAuthState();
      }
    }
    
    // No auth state or it failed - authenticate fresh
    console.log('🔐 Performing fresh authentication...');
    context = await browser.newContext();
    const page = await context.newPage();
    
    const success = await setupAuthentication(page);
    if (!success) {
      await context.close();
      throw new Error('Authentication failed - cannot proceed with tests');
    }
    
    console.log('✓ Authenticated page ready');
    await use(page);
    await context.close();
  },
});

export { expect } from '@playwright/test';

