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

test('E2E 2FA Flow with German Localization and Dark Mode Email', async ({ page, context }) => {
  const username = 'admin_' + Date.now();
  const email = username + '@example.com';
  const password = 'admin';

  test.setTimeout(120000);
  // Listen for console logs and errors
  page.on('console', msg => console.log(`BROWSER LOG: ${msg.text()} `));
  page.on('pageerror', exception => console.log(`BROWSER ERROR: ${exception} \nStack: ${exception.stack} `));
  page.on('response', async response => {
    if (response.status() >= 500) {
      console.log(`BROWSER RESP ${response.status()}: ` + await response.text().catch(() => 'No Body'));
    }
  });

  // 1. Reset Settings to ensure SMTP works (Backdoor)
  await page.request.post('http://localhost:5001/api/debug/fix-settings');

  // 1. Logic: Register or Login as Admin
  await page.goto('http://localhost:5001');

  // Wait for Auth Page to load (Login text or Register button)
  try {
    const loginText = page.locator('text="Sign In"'); // Try finding "Sign In" or "Login"
    await expect(page.locator('form input[name="username"]')).toBeVisible({ timeout: 10000 });
  } catch (e) {
    console.log('Not on login page directly? checking...');
  }

  // Attempt to register first (fresh env)
  let isLoggedIn = false;
  try {
    // Check if we are on auth page by looking for Register tab btn
    const registerBtn = page.getByRole('button', { name: 'Register' });

    // Check if username input is visible (meaning we are on Auth page)
    if (await page.locator('input[name="username"]').isVisible()) {
      if (await registerBtn.isVisible()) {
        await registerBtn.click();
        await page.fill('input[name="username"]', username);
        await page.fill('input[name="email"]', email);
        await page.fill('input[name="password"]', password);
        await page.click('button[type="submit"]'); // Create Account

        // Wait a bit to see if we logged in
        try {
          await expect(page.locator('[data-testid="fab-create-task"]').or(page.locator('[data-testid="logged-in-debug"]'))).toBeVisible({ timeout: 2000 });
          isLoggedIn = true;
        } catch (e) {
          console.log('Registration did not log us in immediately. checking for errors or trying login...');
        }
      }

      if (!isLoggedIn) {
        // Try Login
        console.log('Switching to Login...');
        const loginBtn = page.getByRole('button', { name: 'Login' }); // Tab button
        if (await loginBtn.isVisible()) await loginBtn.click();

        await page.fill('input[name="username"]', username);
        await page.fill('input[name="password"]', password);
        await page.click('button[type="submit"]');
      }
    } else {
      console.log('Username input not visible, assuming already logged in.');
      isLoggedIn = true;
    }
  } catch (e) {
    console.log('Auth flow error:', e);
  }

  // Verify we are actually logged in OR hit 2FA
  try {
    // Check for FAB (Logged in) OR 2FA Header
    // Check for FAB (Logged in) OR Debug Div (LoggedIn) OR 2FA Header
    const fab = page.locator('[data-testid="fab-create-task"]').or(page.locator('[data-testid="logged-in-debug"]'));
    const twoFaHeader = page.locator('text=2FA Verification'); // English default
    const twoFaHeaderDe = page.locator('text=2FA Verifizierung'); // German

    // Wait for any of these
    await Promise.race([
      expect(fab).toBeVisible({ timeout: 5000 }),
      expect(twoFaHeader).toBeVisible({ timeout: 5000 }),
      expect(twoFaHeaderDe).toBeVisible({ timeout: 5000 })
    ]);

    if (await twoFaHeader.isVisible() || await twoFaHeaderDe.isVisible()) {
      console.log('Hit 2FA screen, solving...');
      // Fetch Code
      await page.waitForTimeout(2000);
      const mailhogRes = await page.request.get('http://localhost:8025/api/v2/messages');
      const messages = await mailhogRes.json();
      const latestMessage = messages.items[0];
      const body = latestMessage.Content.Body;
      const code = body.match(/\d{6}/)[0];

      await page.fill('input[type="text"]', code);
      await page.click('button[type="submit"]'); // Verify

      // Now wait for FAB
      await expect(fab).toBeVisible({ timeout: 5000 });
    } else {
      console.log('Logged in directly (No 2FA)');
    }

    // Force Complete Routines to bypass Blocker
    console.log('Force completing routines...');
    await page.request.post('http://localhost:5001/api/user/routine/morning/complete');
    await page.request.post('http://localhost:5001/api/user/routine/evening/complete');

    // Disable Global Routine Blocker via API (Admin Settings)
    console.log('Disabling Global Routine Blocker via API...');
    await page.request.post('http://localhost:5001/api/admin/settings', {
      data: {
        evening_routine_enabled: "false",
        morning_routine_enabled: "false",
        smtp_host: "localhost",
        smtp_port: "1025",
        smtp_user: "",
        smtp_pass: "",
        smtp_from: "noreply@example.com",
        smtp_secure: "false"
      }
    });

    // Reload to pick up new settings
    console.log('Reloading to apply settings...');
    await page.reload();
    await page.waitForTimeout(3000); // Wait for initialization

  } catch (e) {
    console.log('Current URL:', page.url());
    throw new Error('Failed to login/register');
  }



  // 2. Logic: Ensure 2FA is Enabled & Set Language to German
  await page.goto('http://localhost:5001/settings');

  // Wait for loader to disappear
  await expect(page.locator('.animate-spin')).toHaveCount(0, { timeout: 10000 });

  // Verify we are on settings page. 
  try {
    await expect(page.locator('[data-testid="text-settings-title"]')).toBeVisible({ timeout: 10000 });
  } catch (e) {
    console.log('Current URL:', page.url());
    console.log('Page content snapshot:', await page.content());
    throw e;
  }

  // Ensure Language is English first (to reliably find 2FA switch if using text) or use ID
  // Ensure Language is English first (to reliably find 2FA switch if using text) or use ID
  await page.addStyleTag({ content: 'vite-error-overlay { display: none !important; }' });
  await page.click('[data-testid="select-language"]');
  await page.click('[data-testid="option-language-en"]');
  await page.waitForTimeout(500); // persist

  // Enable 2FA if not enabled
  // We can check the privacy API or just toggle.
  // Let's toggle it ON.
  // Switch ID/locating
  // In settings.tsx loop:

  // Use getByText to be more robust
  const twoFaText = page.getByText('Two-Factor Authentication', { exact: false }).first();
  try {
    await expect(twoFaText).toBeVisible({ timeout: 5000 });
  } catch (e) {
    console.log('2FA Text not found. Page content:');
    console.log(await page.content());
    throw e;
  }

  // Find switch in the same container. 
  // Structure: div > [text], Switch
  // We can go up to parent div.
  const twoFaSwitch = page.locator('div.flex.items-center.justify-between').filter({ has: twoFaText }).getByRole('switch');

  const isChecked = await twoFaSwitch.getAttribute('aria-checked') === 'true';
  if (!isChecked) {
    console.log('Enabling 2FA...');
    await twoFaSwitch.click();
    await page.waitForTimeout(1000); // persist
  }

  // Set Language to German
  await page.click('[data-testid="select-language"]');
  await page.click('[data-testid="option-language-de"]');

  // Wait for persistence (API call)
  await page.waitForTimeout(1000);

  // 3. Logic: Logout
  // Use sidebar logout or header logout?
  // AppSidebar has logout button.
  // We need to trigger sidebar if mobile, or just find the button.
  // Button title="Logout"
  // Assuming Sidebar is visible (desktop) or we open it.
  // The test runs in desktop view by default in playwright config usually.
  const logoutBtn = page.locator('button[title="Logout"]');
  // If not visible, might be in a menu.
  // Sidebar usually has it.
  if (await logoutBtn.isVisible()) {
    await logoutBtn.click();
  } else {
    // Try finding by icon or text "Logout" / "Abmelden"
    // In German: "Abmelden"?
    // Let's use URL fallback if UI fails
    await page.goto('http://localhost:5001/api/logout');
    // API logout returns 200 or redirect.
    // But client state needs to be cleared?
    // Better to use UI. 
    // Find "Log out" text?
    // Sidebar footer user menu?

    // Let's try locating any button with Log out text (or German Abmelden)
    const logoutTextBtn = page.locator('button:has-text("Abmelden")');
    if (await logoutTextBtn.isVisible()) {
      await logoutTextBtn.click();
    } else {
      // Fallback: clear cookies/storage manually?
      // No, let's assume Sidebar is there.
      // Maybe checking 'button[data-testid="sidebar-logout"]' if added?

      // If failing, let's force navigate
      await page.goto('http://localhost:5001/auth?mode=login');
      // But query cache might persist user?
      // The app checks /api/user. If cookie is gone, it returns 401.
      await context.clearCookies();
      await page.reload();
    }
  }

  await page.waitForURL(/.*\/auth/);

  // 4. Logic: Login again to trigger 2FA (Now in German context)
  await page.fill('input[name="username"]', username);
  await page.fill('input[name="password"]', password);

  // Capture response to get debug code if SMTP fails
  const loginResponsePromise = page.waitForResponse(response => response.url().includes('/api/login') && response.request().method() === 'POST');

  await page.click('button[type="submit"]');

  const loginResponse = await loginResponsePromise;
  const loginJson = await loginResponse.json();
  const debugCode = loginJson.debugCode;

  // Verify 2FA Screen - Should have German title "2FA-Verifizierung"
  // Note: Translation key 'auth.2faVerification'.
  // Ensure we check for the GERMAN text.
  await expect(page.locator('text=2FA Verifizierung')).toBeVisible({ timeout: 5000 });

  let code = debugCode;

  if (!code) {
    // 5. Logic: Fetch Code from MailHog
    // Use existing request context
    await page.waitForTimeout(2000);
    const mailhogRes2 = await page.request.get('http://localhost:8025/api/v2/messages');
    const messages2 = await mailhogRes2.json();
    const latestMessage2 = messages2.items[0];

    // Verify Email Subject and Body (German)
    expect(latestMessage2.Content.Headers.Subject[0]).toContain('Ihr 2FA-Verifizierungscode');

    const emailBody = latestMessage2.Content.Body;
    // Verify Dark Mode (HTML check)
    expect(emailBody).toContain('background-color: #09090b'); // Dark background
    expect(emailBody).toContain('#fafafa'); // Light text
    expect(emailBody).toContain('Verifizierungscode');

    code = emailBody.match(/\d{6}/)[0];
    console.log('Got German 2FA Code from MailHog:', code);
  } else {
    console.log('Using Debug 2FA Code from response:', code);
  }

  // 6. Logic: Enter Code
  await page.getByPlaceholder('123456').fill(code);
  // Button text might be "Überprüfen" or "Verifizieren"
  // We can use the button type submit, or look for the text.
  // In German de.json, auth.verify usually translates to "Verifizieren" or "Bestätigen"
  // Let's use the submit button generic locator since it's the only one
  await page.click('button[type="submit"]');

  // 7. Logic: Success
  await page.waitForTimeout(3000);
  await expect(page).toHaveURL('http://localhost:5001/');

  // 8. Restore Language to English for future tests (Optional)
  await page.goto('http://localhost:5001/settings');
  await page.click('[data-testid="select-language"]');
  await page.click('[data-testid="option-language-en"]');
});
