import { test, expect } from '@playwright/test';
import { authenticateUser, ShopFlowAuthenticator } from '../../utils/authentication';
import { testConfig } from '../../utils/test-config';
import { printTestCase, printSuccess, printWarning } from '../../helpers/test-helpers';
import { expectAuthenticated, expectSessionValid, expectOnPage } from '../../helpers/assertions';

/**
 * Comprehensive Login Test
 * Tags: @auth @p1 @smoke
 * 
 * Mirrors Katalon's Login test case with full verification
 * Tests the complete login flow including 2FA
 */

test.describe('01_Authentication - Login @auth @p1 @smoke', () => {
  
  test('Test Case 1: Initial setup and navigation', async ({ page }) => {
    printTestCase(1, 'Initial Setup and Navigation');
    
    // Navigate to login page
    await page.goto('/');
    await page.waitForTimeout(2000);
    
    printSuccess('Navigated to base URL');
    
    // Verify page loaded correctly
    const pageTitle = await page.title();
    expect(pageTitle).toBeTruthy();
    expect(pageTitle.trim()).not.toBe('');
    printSuccess(`Login page loaded successfully: ${pageTitle}`);
    
    // Check login form elements are present
    const emailField = page.locator('input[type="email"], input[placeholder*="email" i], input[name*="email" i]');
    const passwordField = page.locator('input[type="password"], input[placeholder*="password" i]');
    const loginButton = page.locator('button:has-text("LOGIN"), button:has-text("Login"), input[type="submit"]');
    
    const hasEmailField = await emailField.first().isVisible({ timeout: 5000 }).catch(() => false);
    const hasPasswordField = await passwordField.first().isVisible({ timeout: 5000 }).catch(() => false);
    const hasLoginButton = await loginButton.first().isVisible({ timeout: 5000 }).catch(() => false);
    
    expect(hasEmailField).toBe(true);
    expect(hasPasswordField).toBe(true);
    expect(hasLoginButton).toBe(true);
    
    printSuccess(`Login form elements found: Email=${hasEmailField}, Password=${hasPasswordField}, Button=${hasLoginButton}`);
  });
  
  test('Test Case 2: Login form structure verification', async ({ page }) => {
    printTestCase(2, 'Login Form Structure Verification');
    
    await page.goto('/');
    await page.waitForTimeout(2000);
    
    // Verify email field
    const emailField = page.locator('input[type="email"], input[placeholder*="email" i], input[name*="email" i]').first();
    await expect(emailField).toBeVisible();
    printSuccess('Email field is present and visible');
    
    // Verify password field
    const passwordField = page.locator('input[type="password"], input[placeholder*="password" i]').first();
    await expect(passwordField).toBeVisible();
    printSuccess('Password field is present and visible');
    
    // Verify login button
    const loginButton = page.locator('button:has-text("LOGIN"), button:has-text("Login"), input[type="submit"]').first();
    await expect(loginButton).toBeVisible();
    printSuccess('Login button is present and visible');
    
    // Note: Remember me functionality is on the 2FA screen, not the login screen
    
    // Check for forgot password link (optional)
    const forgotPassword = page.locator('a:has-text("Forgot password"), a:has-text("Forgot Password")');
    const hasForgotPassword = await forgotPassword.isVisible({ timeout: 3000 }).catch(() => false);
    if (hasForgotPassword) {
      printSuccess('Forgot password functionality is available');
    } else {
      printWarning('Forgot password functionality not found');
    }
  });
  
  test('Test Case 3: Enter login credentials', async ({ page }) => {
    printTestCase(3, 'Enter Login Credentials');
    
    await page.goto('/');
    await page.waitForTimeout(2000);
    
    const emailField = page.locator('input[type="email"], input[placeholder*="email" i], input[name*="email" i]').first();
    const passwordField = page.locator('input[type="password"], input[placeholder*="password" i]').first();
    
    // Clear and enter email
    await emailField.clear();
    await emailField.fill(testConfig.testEmail);
    printSuccess('Email entered');
    
    // Clear and enter password
    await passwordField.clear();
    await passwordField.fill(testConfig.testPassword);
    printSuccess('Password entered');
    
    // Verify credentials were entered
    const enteredEmail = await emailField.inputValue();
    expect(enteredEmail).toBe(testConfig.testEmail);
    printSuccess('Email entered correctly');
    
    const enteredPassword = await passwordField.inputValue();
    expect(enteredPassword).toBe(testConfig.testPassword);
    printSuccess('Password entered correctly');
  });
  
  test('Test Case 4: Submit login form', async ({ page }) => {
    printTestCase(4, 'Submit Login Form');
    
    await page.goto('/');
    await page.waitForTimeout(2000);
    
    // Fill credentials
    await page.locator('input[type="email"], input[placeholder*="email" i], input[name*="email" i]').first().fill(testConfig.testEmail);
    await page.locator('input[type="password"], input[placeholder*="password" i]').first().fill(testConfig.testPassword);
    
    // Capture timestamp for 2FA email tracking
    const loginTimestamp = new Date();
    console.log(`Login attempt timestamp: ${loginTimestamp.toISOString()}`);
    
    // Click login button
    const loginButton = page.locator('button:has-text("LOGIN"), button:has-text("Login"), input[type="submit"]').first();
    await loginButton.click();
    printSuccess('Login button clicked');
    
    // Wait for response
    await page.waitForTimeout(3000);
    printSuccess('Waited for login response');
  });
  
  test('Test Case 5-8: Complete login flow with 2FA', async ({ page }) => {
    printTestCase(5, 'Complete Login Flow with 2FA Verification');
    
    // Use the authentication utility for complete flow
    const result = await authenticateUser(page);
    
    if (!result.success) {
      console.error('Authentication failed:', result.error || 'Unknown error');
      console.error('Session valid:', result.sessionValid);
    }
    
    expect(result.success).toBe(true);
    printSuccess('Authentication completed successfully');
    
    if (result.username) {
      printSuccess(`Logged in as: ${result.username}`);
    }
    
    if (result.redirectUrl) {
      printSuccess(`Redirected to: ${result.redirectUrl}`);
    }
    
    // Test Case 6: Verify successful login
    printTestCase(6, 'Verify Successful Login');
    
    // Wait for navigation away from login page (pattern from passing tests)
    // After successful login, user is redirected to /home or /shop
    // Wait for URL to change away from login/2fa pages
    try {
      await page.waitForURL(url => {
        const urlStr = url.toString();
        return !urlStr.includes('/login') && !urlStr.includes('/2fa') && !urlStr.includes('/2fa-validation');
      }, { timeout: 10000 });
    } catch {
      // If URL doesn't change, check current URL
    }
    
    // Wait for authenticated indicators to appear (confirms navigation completed)
    // This ensures the new page has fully loaded before checking for login form absence
    const authenticatedIndicators = [
      page.locator('img.avatar, .avatar'),
      page.locator('a.nav-link.dropdown-toggle:has(img.avatar)'),
      page.locator('.fw-500.text-primary'), // User fullname
    ];
    
    let isAuthenticated = false;
    for (const indicator of authenticatedIndicators) {
      if (await indicator.isVisible({ timeout: 10000 }).catch(() => false)) {
        isAuthenticated = true;
        // Wait for page to be fully loaded after authenticated indicator appears
        await page.waitForLoadState('networkidle').catch(() => {});
        break;
      }
    }
    
    // Check we're not on login page by verifying:
    // 1. URL doesn't contain /login or /2fa
    const currentUrl = page.url();
    const isOnLoginPage = currentUrl.includes('/login') || currentUrl.includes('/2fa') || currentUrl.includes('/2fa-validation');
    
    // 2. Login form element doesn't exist in DOM (user confirmed this will never happen when authenticated)
    // Based on login.php: the email input has id="inputEmail"
    const loginFormExists = await page.locator('#inputEmail').count() > 0;
    
    // Check for 2FA form existence
    const twoFAFormExists = (await page.locator('input[type="number"], input[type="text"][placeholder*="code" i], input[role="spinbutton"]').count()) > 0;
    
    expect(isOnLoginPage).toBe(false);
    expect(isAuthenticated).toBe(true);
    expect(loginFormExists).toBe(false);
    expect(twoFAFormExists).toBe(false);
    printSuccess('Successfully redirected away from login/2FA page');
    
    // Verify session indicators
    await expectAuthenticated(page);
    printSuccess('User authentication indicators verified');
    
    // Test Case 7: Test session management
    printTestCase(7, 'Test Session Management');
    
    // Navigate to protected page
    await page.goto('/shop');
    await page.waitForTimeout(2000);
    
    // Verify we can access protected page
    const shopUrl = page.url();
    expect(shopUrl).toContain('/shop');
    printSuccess('Session maintained - can access protected pages');
    
    // Validate session is still valid
    await expectSessionValid(page);
    printSuccess('Session is valid');
    
    // Test Case 8: Test logout availability
    printTestCase(8, 'Test Logout Availability');
    
    // Look for logout button/link
    const logoutButton = page.locator('a:has-text("Logout"), button:has-text("Logout"), a:has-text("Log out")').first();
    const hasLogout = await logoutButton.isVisible({ timeout: 5000 }).catch(() => false);
    
    if (hasLogout) {
      printSuccess('Logout button is available');
    } else {
      printWarning('Logout button not clearly visible (may be in dropdown)');
    }
    
    printSuccess('=== Login Test Completed Successfully ===');
  });
});

