/**
 * E2E Test: Passwordless Login Flow
 *
 * Tests the complete passwordless login experience:
 * 1. Login page defaults to OTP mode (no password field)
 * 2. User enters email only
 * 3. System sends personalized OTP
 * 4. User verifies OTP
 * 5. User logged in to dashboard
 */

import { test, expect } from '@playwright/test';

const APP_URL = 'http://localhost:9000';
const MAILHOG_API = 'http://localhost:8025/api/v2';

async function getLatestEmailForAddress(email: string): Promise<any> {
  const response = await fetch(`${MAILHOG_API}/messages`);
  const data = await response.json();

  const userEmails = data.items.filter((item: any) => {
    const toHeader = item.Content?.Headers?.To?.[0] || '';
    return toHeader.includes(email);
  });

  return userEmails.length > 0 ? userEmails[0] : null;
}

function extractOTP(emailData: any): string | null {
  const body = emailData?.Content?.Body || '';
  const match = body.match(/(\d{6})/);
  return match ? match[1] : null;
}

async function clearMailHog() {
  await fetch(`${MAILHOG_API}/messages`, { method: 'DELETE' });
}

// Helper: Create a test user for login testing
async function createTestUser(email: string, name: string) {
  const response = await fetch(`${APP_URL}/api/auth/check-email?email=${encodeURIComponent(email)}`);
  const data = await response.json();

  return data.exists;
}

test.describe('Passwordless Login Flow', () => {

  test('login page should default to OTP mode (no password field)', async ({ page }) => {
    await page.goto(`${APP_URL}/en/login`);

    // Password field should NOT be visible by default
    const passwordInput = page.locator('input[type="password"]');
    const passwordVisible = await passwordInput.isVisible().catch(() => false);

    expect(passwordVisible).toBe(false);
    console.log('✅ Password field hidden by default');

    // Passwordless notice should be visible
    await expect(page.locator('text=/passwordless.*login|verification.*email/i')).toBeVisible();
    console.log('✅ Passwordless notice shown');

    // Should have "Or use password" option
    await expect(page.locator('text=/use password|password instead/i')).toBeVisible();
    console.log('✅ Password option link available');
  });

  test('should toggle between OTP and password modes', async ({ page }) => {
    await page.goto(`${APP_URL}/en/login`);

    // Default: OTP mode (no password field)
    let passwordField = page.locator('input[type="password"]');
    expect(await passwordField.isVisible().catch(() => false)).toBe(false);

    // Click "Or use password"
    await page.click('text=/use password|password instead/i');
    await page.waitForTimeout(500);

    // Password field should now be visible
    passwordField = page.locator('input[type="password"]');
    await expect(passwordField).toBeVisible();
    console.log('✅ Switched to password mode');

    // Click "Use OTP instead"
    await page.click('text=/use otp|otp instead/i').catch(() => {
      console.log('OTP link not found, might already be in OTP mode');
    });
    await page.waitForTimeout(500);

    // Password field should be hidden again
    const passwordVisible = await page.locator('input[type="password"]').isVisible().catch(() => false);
    expect(passwordVisible).toBe(false);
    console.log('✅ Switched back to OTP mode');
  });

  test('should complete full passwordless login flow', async ({ page, request }) => {
    const testEmail = 'gara2222ge@support.com'; // Existing account

    await clearMailHog();

    // Step 1: Navigate to login
    await page.goto(`${APP_URL}/en/login`);

    // Step 2: Verify we're in OTP mode (default)
    const passwordVisible = await page.locator('input[type="password"]').isVisible().catch(() => false);
    expect(passwordVisible).toBe(false);

    // Step 3: Enter email
    const emailInput = page.locator('input[type="text"], input[id="identifier"]').first();
    await emailInput.fill(testEmail);
    console.log(`✅ Entered email: ${testEmail}`);

    // Step 4: Click Send OTP
    const sendButton = page.locator('button[type="submit"]:has-text("Send"), button:has-text("OTP"), button[type="submit"]').first();
    await sendButton.click();
    console.log('✅ Clicked Send OTP');

    // Step 5: Should move to OTP input step
    await expect(page.locator('text=/Enter.*code|OTP|verification/i')).toBeVisible({ timeout: 5000 });
    console.log('✅ Moved to OTP input step');

    // Step 6: Wait for email
    await page.waitForTimeout(3000);

    // Step 7: Get OTP from MailHog
    const emailData = await getLatestEmailForAddress(testEmail);
    expect(emailData).toBeTruthy();
    console.log('✅ Login OTP email received');

    // Step 8: Verify email says "log in" not "signup"
    const emailBody = emailData.Content.Body;
    expect(emailBody).toMatch(/log.*in|login/i);
    expect(emailBody).not.toMatch(/thank you for choosing|signup|registration/i);
    console.log('✅ Email has correct login message');

    // Step 9: Extract and enter OTP
    const otpCode = extractOTP(emailData);
    expect(otpCode).toBeTruthy();
    console.log(`✅ OTP extracted: ${otpCode}`);

    const otpInput = page.locator('input[inputmode="numeric"], input[type="text"]').first();
    await otpInput.fill(otpCode!);

    // Step 10: Verify and login
    const verifyButton = page.locator('button:has-text("Verify"), button:has-text("Login"), button[type="submit"]').first();
    await verifyButton.click();
    console.log('✅ Clicked verify');

    // Step 11: Should redirect to dashboard
    await expect(page).toHaveURL(/\/dashboard/, { timeout: 10000 });
    console.log('✅ Logged in successfully!');
  });

  test('should handle invalid OTP gracefully', async ({ page }) => {
    const testEmail = 'gara2222ge@support.com';

    await page.goto(`${APP_URL}/en/login`);
    await page.locator('input[type="text"]').first().fill(testEmail);
    await page.locator('button[type="submit"]').first().click();

    // Wait for OTP step
    await expect(page.locator('text=/Enter.*code|OTP/i')).toBeVisible({ timeout: 5000 });

    // Enter invalid OTP
    const otpInput = page.locator('input[inputmode="numeric"], input[type="text"]').first();
    await otpInput.fill('999999');

    // Try to verify
    await page.locator('button:has-text("Verify"), button[type="submit"]').first().click();

    // Should show error message
    await expect(page.locator('text=/invalid.*code|expired.*code|incorrect/i')).toBeVisible({ timeout: 5000 });
    console.log('✅ Invalid OTP error shown');
  });

  test('should allow resending OTP code', async ({ page }) => {
    const testEmail = 'gara2222ge@support.com';

    await clearMailHog();
    await page.goto(`${APP_URL}/en/login`);

    await page.locator('input[type="text"]').first().fill(testEmail);
    await page.locator('button[type="submit"]').first().click();

    // Wait for OTP step
    await expect(page.locator('text=/Enter.*code|OTP/i')).toBeVisible({ timeout: 5000 });

    // Clear previous emails
    await clearMailHog();

    // Wait for resend button to be enabled (or click if already enabled)
    await page.waitForTimeout(1000);

    const resendButton = page.locator('button:has-text("Resend"), a:has-text("Resend")');
    if (await resendButton.isVisible()) {
      await resendButton.click();
      console.log('✅ Clicked resend');

      // Wait for new email
      await page.waitForTimeout(3000);

      // Verify new email was sent
      const emailData = await getLatestEmailForAddress(testEmail);
      expect(emailData).toBeTruthy();
      console.log('✅ New OTP email sent after resend');
    }
  });

  test('should show back button to return to email input', async ({ page }) => {
    const testEmail = 'gara2222ge@support.com';

    await page.goto(`${APP_URL}/en/login`);
    await page.locator('input[type="text"]').first().fill(testEmail);
    await page.locator('button[type="submit"]').first().click();

    // At OTP step
    await expect(page.locator('text=/Enter.*code|OTP/i')).toBeVisible({ timeout: 5000 });

    // Should have back button
    const backButton = page.locator('button:has-text("Back"), a:has-text("Back")');
    await expect(backButton).toBeVisible();

    // Click back
    await backButton.click();
    await page.waitForTimeout(500);

    // Should be back at email input
    const emailInput = page.locator('input[type="text"]').first();
    await expect(emailInput).toBeVisible();
    console.log('✅ Back button works');
  });
});
