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

test.describe('Booking Flow End-to-End', () => {
  const ADMIN_URL = 'http://localhost:55581';
  const ADMIN_EMAIL = 'admin@mccars.local';
  const ADMIN_PASSWORD = 'mc-cars-admin';

  // Generate unique test data per run to avoid conflicts
  const ts = Date.now();
  const testEmails = [
    `test-day-${ts}@playwright.test`,
    `test-weekend-${ts}@playwright.test`,
    `test-custom-${ts}@playwright.test`,
  ];
  const testNames = [
    'Test Testerson Day',
    'Test Testerson Weekend',
    'Test Testerson Custom',
  ];

  /**
   * Helper: fill out the booking form for a given mietdauer type.
   * Returns nothing - the form submission is handled by the page's JS.
   */
  async function submitBooking(page, type, index) {
    // Scroll to booking section
    await page.locator('#buchen').scrollIntoViewIfNeeded();
    await page.waitForTimeout(500);

    // Step 1: Select vehicle
    const carSelect = page.locator('#bpfCar');
    await expect(carSelect).toBeVisible({ timeout: 10000 });
    // Select first available vehicle option (skip the placeholder)
    const options = await carSelect.locator('option').all();
    expect(options.length).toBeGreaterThan(1);
    const firstVehicle = await options[1].innerText();
    await carSelect.selectOption({ label: firstVehicle });

    // Step 2: Select mietdauer type
    const presetBtn = page.locator(`.bpf-preset[data-preset="${type}"]`);
    await expect(presetBtn).toBeVisible();
    await presetBtn.click();

    // Step 3: Pick date(s) based on type
    if (type === 'day') {
      // Pick a date 7 days from now
      const futureDate = new Date();
      futureDate.setDate(futureDate.getDate() + 7);
      const dateStr = futureDate.toISOString().split('T')[0];
      const dateInput = page.locator('#bpfDayDate');
      await dateInput.fill(dateStr);
    } else if (type === 'weekend') {
      // Pick next Saturday
      const nextSaturday = new Date();
      const daysUntilSaturday = (6 - nextSaturday.getDay() + 7) % 7 || 7;
      nextSaturday.setDate(nextSaturday.getDate() + daysUntilSaturday);
      const dateStr = nextSaturday.toISOString().split('T')[0];
      const dateInput = page.locator('#bpfWeekendDate');
      await dateInput.fill(dateStr);
    } else if (type === 'custom') {
      // Pick start date 14 days from now, end date 17 days from now (4 days = individuell)
      const startDate = new Date();
      startDate.setDate(startDate.getDate() + 14);
      const endDate = new Date(startDate);
      endDate.setDate(endDate.getDate() + 3);
      const fromStr = startDate.toISOString().split('T')[0];
      const toStr = endDate.toISOString().split('T')[0];
      await page.locator('#bpfFrom').fill(fromStr);
      await page.locator('#bpfTo').fill(toStr);
    }

    // Click Weiter to go to step 2
    await page.locator('#bpfNext1').click();
    await page.waitForTimeout(300);

    // Step 2: Fill contact info
    await expect(page.locator('#bpfName')).toBeVisible();
    await page.locator('#bpfName').fill(testNames[index]);
    await page.locator('#bpfEmail').fill(testEmails[index]);
    await page.locator('#bpfPhone').fill('+43 660 1234567');
    await page.locator('#bpfMessage').fill(`Test booking via playwright - ${type}`);

    // Click Weiter to go to step 3
    await page.locator('#bpfNext2').click();
    await page.waitForTimeout(300);

    // Step 3: Submit (skip file uploads - they are optional)
    await expect(page.locator('#bpfSubmit')).toBeVisible();
    await page.locator('#bpfSubmit').click();

    // Wait for success toast
    await expect(page.locator('#toast.show')).toBeVisible({ timeout: 10000 });
    await page.waitForTimeout(1000);
  }

  test('Complete booking flow: 1 Tag, Wochenende, Individuell → 3 leads in admin → disqualify all', async ({ page, context }) => {
    // ========================================
    // PART 1: Submit 3 bookings on main site
    // ========================================
    await page.goto('/');
    await page.waitForLoadState('domcontentloaded');
    await page.waitForTimeout(2000);

    // Booking 1: 1 Tag
    await submitBooking(page, 'day', 0);

    // Booking 2: Wochenende
    await submitBooking(page, 'weekend', 1);

    // Booking 3: Individuell
    await submitBooking(page, 'custom', 2);

    // ========================================
    // PART 2: Verify 3 leads in admin panel
    // ========================================
    const adminCtx = await test.info().project.use.baseBrowserType?.newContext() ?? context;
    const adminPage = await adminCtx.newPage();
    adminPage.setDefaultTimeout(30000);

    await adminPage.goto(ADMIN_URL);
    await adminPage.waitForLoadState('domcontentloaded');
    await adminPage.waitForTimeout(2000);

    // Login
    const loginForm = adminPage.locator('#loginForm');
    await expect(loginForm).toBeVisible({ timeout: 10000 });
    await adminPage.locator('#loginForm [name="email"]').fill(ADMIN_EMAIL);
    await adminPage.locator('#loginForm [name="password"]').fill(ADMIN_PASSWORD);
    await adminPage.locator('#loginForm [type="submit"]').click();

    // Wait a moment for login to process
    await adminPage.waitForTimeout(3000);

    // Check for login error
    const loginError = adminPage.locator('#loginError');
    if (await loginError.isVisible()) {
      const errorMsg = await loginError.textContent();
      throw new Error(`Login failed: ${errorMsg}`);
    }

    // Check if password rotation is required (first login)
    const rotateView = adminPage.locator('#rotateView');
    if (await rotateView.isVisible({ timeout: 2000 })) {
      // Set a new password (must be different from bootstrap)
      const newPw = 'Playwright-Test-PW-2026!';
      await adminPage.locator('#rotateForm [name="pw1"]').fill(newPw);
      await adminPage.locator('#rotateForm [name="pw2"]').fill(newPw);
      await adminPage.locator('#rotateForm [type="submit"]').click();
      await adminPage.waitForTimeout(2000);
    }

    // Wait for admin view to load
    await expect(adminPage.locator('#adminView')).toBeVisible({ timeout: 15000 });
    await adminPage.waitForTimeout(2000);

    // Ensure leads tab is active (it's the default)
    const leadsTab = adminPage.locator('[data-tab="leads"]');
    const leadsTabClass = await leadsTab.getAttribute('class');
    if (!leadsTabClass?.includes('active')) {
      await leadsTab.click();
      await adminPage.waitForTimeout(1000);
    }

    // Wait for our test leads to appear by checking for their emails in the table
    // We wait for at least one of our test emails to appear, then verify all 3
    await adminPage.waitForFunction(
      ([emails]) => {
        const rows = document.querySelectorAll('#leadsTable tbody tr');
        let found = 0;
        for (const row of rows) {
          const text = row.textContent;
          for (const email of emails) {
            if (text.includes(email)) {
              found++;
              break;
            }
          }
        }
        return found >= 3;
      },
      testEmails,
      { timeout: 30000 }
    );

    await adminPage.waitForTimeout(1000);

    // Find our test leads by email pattern
    const allRows = adminPage.locator('#leadsTable tbody tr');
    const totalRows = await allRows.count();
    const testRowIndices = [];

    for (let i = 0; i < totalRows; i++) {
      const row = allRows.nth(i);
      const rowText = await row.textContent();
      if (testEmails.some(email => rowText.includes(email))) {
        testRowIndices.push(i);
      }
    }

    expect(testRowIndices.length).toBe(3);

    // ========================================
    // PART 3: Disqualify all 3 test leads
    // ========================================
    // Disqualify each lead one at a time, re-finding it after each disqualification
    // since the table re-renders and indices shift.
    for (const email of testEmails) {
      // Find the row for this email
      const rows = adminPage.locator('#leadsTable tbody tr');
      const count = await rows.count();
      let found = false;

      for (let i = 0; i < count; i++) {
        const rowText = await rows.nth(i).textContent();
        if (rowText.includes(email)) {
          // Click disqualify button
          const disqBtn = rows.nth(i).locator('[data-disq]');
          if (await disqBtn.isVisible()) {
            await disqBtn.click();
            await adminPage.waitForTimeout(1500);
            found = true;
            break;
          }
        }
      }

      expect(found).toBe(true, `Lead with email ${email} not found or could not be disqualified`);
    }

    // Wait for disqualifications to process
    await adminPage.waitForTimeout(2000);

    // Refresh page to ensure fresh data after disqualifications
    await adminPage.reload();
    await expect(adminPage.locator('#adminView')).toBeVisible({ timeout: 15000 });
    await adminPage.waitForTimeout(3000);

    // Verify our test leads are now disqualified (no longer in active view)
    const remainingRows = adminPage.locator('#leadsTable tbody tr');
    const remainingCount = await remainingRows.count();
    let foundTestLead = false;

    for (let i = 0; i < remainingCount; i++) {
      const rowText = await remainingRows.nth(i).textContent();
      if (testEmails.some(email => rowText.includes(email))) {
        foundTestLead = true;
        break;
      }
    }

    expect(foundTestLead).toBe(false);

    await adminPage.close();
  });
});
