/**
 * E2E Test - Complete Booking Workflow
 *
 * Tests the complete booking flow from rate search to booking confirmation
 */

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

// Test configuration
const BASE_URL = process.env.BASE_URL || 'http://localhost:3000';
const API_URL = process.env.API_URL || 'http://localhost:4000/api/v1';

// Test user credentials (should be set via environment variables)
const TEST_USER = {
  email: process.env.TEST_USER_EMAIL || 'test@example.com',
  password: process.env.TEST_USER_PASSWORD || 'TestPassword123!',
};

test.describe('Complete Booking Workflow', () => {
  test.beforeEach(async ({ page }) => {
    // Navigate to homepage
    await page.goto(BASE_URL);
  });

  test('should complete full booking flow', async ({ page }) => {
    // Step 1: Login
    await test.step('User Login', async () => {
      await page.click('text=Login');
      await page.fill('input[name="email"]', TEST_USER.email);
      await page.fill('input[name="password"]', TEST_USER.password);
      await page.click('button[type="submit"]');

      // Wait for redirect to dashboard
      await page.waitForURL('**/dashboard');
      await expect(page).toHaveURL(/.*dashboard/);
    });

    // Step 2: Navigate to Rate Search
    await test.step('Navigate to Rate Search', async () => {
      await page.click('text=Search Rates');
      await expect(page).toHaveURL(/.*rates\/search/);
    });

    // Step 3: Search for Rates
    await test.step('Search for Shipping Rates', async () => {
      // Fill search form
      await page.fill('input[name="origin"]', 'Rotterdam');
      await page.waitForTimeout(500); // Wait for autocomplete
      await page.keyboard.press('ArrowDown');
      await page.keyboard.press('Enter');

      await page.fill('input[name="destination"]', 'Shanghai');
      await page.waitForTimeout(500);
      await page.keyboard.press('ArrowDown');
      await page.keyboard.press('Enter');

      // Select departure date (2 weeks from now)
      const departureDate = new Date();
      departureDate.setDate(departureDate.getDate() + 14);
      await page.fill('input[name="departureDate"]', departureDate.toISOString().split('T')[0]);

      // Select container type
      await page.selectOption('select[name="containerType"]', '40HC');
      await page.fill('input[name="quantity"]', '1');

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

      // Wait for results
      await page.waitForSelector('.rate-results', { timeout: 10000 });

      // Verify results are displayed
      const resultsCount = await page.locator('.rate-card').count();
      expect(resultsCount).toBeGreaterThan(0);
    });

    // Step 4: Select a Rate and Create Booking
    await test.step('Select Rate and Create Booking', async () => {
      // Select first available rate
      await page.locator('.rate-card').first().locator('button:has-text("Book")').click();

      // Should navigate to booking form
      await expect(page).toHaveURL(/.*bookings\/create/);

      // Fill booking details
      await page.fill('input[name="shipperName"]', 'Test Shipper Inc.');
      await page.fill('input[name="shipperAddress"]', '123 Test St');
      await page.fill('input[name="shipperCity"]', 'Rotterdam');
      await page.fill('input[name="shipperCountry"]', 'Netherlands');
      await page.fill('input[name="shipperEmail"]', 'shipper@test.com');
      await page.fill('input[name="shipperPhone"]', '+31612345678');

      await page.fill('input[name="consigneeName"]', 'Test Consignee Ltd.');
      await page.fill('input[name="consigneeAddress"]', '456 Dest Ave');
      await page.fill('input[name="consigneeCity"]', 'Shanghai');
      await page.fill('input[name="consigneeCountry"]', 'China');
      await page.fill('input[name="consigneeEmail"]', 'consignee@test.com');
      await page.fill('input[name="consigneePhone"]', '+8613812345678');

      // Container details
      await page.fill('input[name="cargoDescription"]', 'Test Cargo - Electronics');
      await page.fill('input[name="cargoWeight"]', '15000'); // kg
      await page.fill('input[name="cargoValue"]', '50000'); // USD

      // Submit booking
      await page.click('button:has-text("Create Booking")');

      // Wait for confirmation
      await page.waitForSelector('.booking-confirmation', { timeout: 10000 });
    });

    // Step 5: Verify Booking in Dashboard
    await test.step('Verify Booking in Dashboard', async () => {
      // Navigate to dashboard
      await page.click('text=Dashboard');
      await expect(page).toHaveURL(/.*dashboard/);

      // Verify new booking appears in list
      await page.waitForSelector('.bookings-table');

      // Check that first row contains the booking
      const firstBooking = page.locator('.booking-row').first();
      await expect(firstBooking).toBeVisible();

      // Verify booking number format (WCM-YYYY-XXXXXX)
      const bookingNumber = await firstBooking.locator('.booking-number').textContent();
      expect(bookingNumber).toMatch(/WCM-\d{4}-[A-Z0-9]{6}/);
    });

    // Step 6: View Booking Details
    await test.step('View Booking Details', async () => {
      // Click on booking to view details
      await page.locator('.booking-row').first().click();

      // Should navigate to booking details page
      await expect(page).toHaveURL(/.*bookings\/[a-f0-9-]+/);

      // Verify all details are displayed
      await expect(page.locator('text=Test Shipper Inc.')).toBeVisible();
      await expect(page.locator('text=Test Consignee Ltd.')).toBeVisible();
      await expect(page.locator('text=Rotterdam')).toBeVisible();
      await expect(page.locator('text=Shanghai')).toBeVisible();
    });
  });

  test('should handle rate search errors gracefully', async ({ page }) => {
    await test.step('Login', async () => {
      await page.goto(`${BASE_URL}/login`);
      await page.fill('input[name="email"]', TEST_USER.email);
      await page.fill('input[name="password"]', TEST_USER.password);
      await page.click('button[type="submit"]');
      await page.waitForURL('**/dashboard');
    });

    await test.step('Test Invalid Search', async () => {
      await page.goto(`${BASE_URL}/rates/search`);

      // Try to search without filling required fields
      await page.click('button[type="submit"]');

      // Should show validation errors
      await expect(page.locator('.error-message')).toBeVisible();
    });
  });

  test('should filter bookings in dashboard', async ({ page }) => {
    await test.step('Login and Navigate to Dashboard', async () => {
      await page.goto(`${BASE_URL}/login`);
      await page.fill('input[name="email"]', TEST_USER.email);
      await page.fill('input[name="password"]', TEST_USER.password);
      await page.click('button[type="submit"]');
      await page.waitForURL('**/dashboard');
    });

    await test.step('Apply Filters', async () => {
      // Open filter panel
      await page.click('button:has-text("Filters")');

      // Filter by status
      await page.check('input[value="confirmed"]');

      // Apply filters
      await page.click('button:has-text("Apply")');

      // Wait for filtered results
      await page.waitForTimeout(1000);

      // Verify all visible bookings have confirmed status
      const bookings = page.locator('.booking-row');
      const count = await bookings.count();

      for (let i = 0; i < count; i++) {
        const status = await bookings.nth(i).locator('.status-badge').textContent();
        expect(status?.toLowerCase()).toContain('confirmed');
      }
    });
  });

  test('should export bookings', async ({ page }) => {
    await test.step('Login and Navigate to Dashboard', async () => {
      await page.goto(`${BASE_URL}/login`);
      await page.fill('input[name="email"]', TEST_USER.email);
      await page.fill('input[name="password"]', TEST_USER.password);
      await page.click('button[type="submit"]');
      await page.waitForURL('**/dashboard');
    });

    await test.step('Export Bookings', async () => {
      // Wait for download event
      const downloadPromise = page.waitForEvent('download');

      // Click export button
      await page.click('button:has-text("Export")');
      await page.click('text=CSV');

      // Wait for download
      const download = await downloadPromise;

      // Verify filename
      expect(download.suggestedFilename()).toMatch(/bookings.*\.csv/);
    });
  });
});

test.describe('Authentication', () => {
  test('should prevent access to protected pages', async ({ page }) => {
    // Try to access dashboard without logging in
    await page.goto(`${BASE_URL}/dashboard`);

    // Should redirect to login
    await expect(page).toHaveURL(/.*login/);
  });

  test('should show error for invalid credentials', async ({ page }) => {
    await page.goto(`${BASE_URL}/login`);

    await page.fill('input[name="email"]', 'wrong@example.com');
    await page.fill('input[name="password"]', 'wrongpassword');
    await page.click('button[type="submit"]');

    // Should show error message
    await expect(page.locator('.error-message')).toBeVisible();
    await expect(page.locator('text=Invalid credentials')).toBeVisible();
  });

  test('should logout successfully', async ({ page }) => {
    // Login first
    await page.goto(`${BASE_URL}/login`);
    await page.fill('input[name="email"]', TEST_USER.email);
    await page.fill('input[name="password"]', TEST_USER.password);
    await page.click('button[type="submit"]');
    await page.waitForURL('**/dashboard');

    // Logout
    await page.click('button:has-text("Logout")');

    // Should redirect to home/login
    await expect(page).toHaveURL(/.*(\/$|\/login)/);
  });
});
