/**
 * E2E Test: Scenario Comparison
 * 
 * Tests for:
 * - Select multiple scenarios
 * - Navigate to compare page
 * - Verify comparison data
 */

import { test, expect } from '@playwright/test';
import { 
  navigateTo, 
  waitForLoading,
  createScenarioViaAPI,
  deleteScenarioViaAPI,
  startScenarioViaAPI,
  sendTestLogs,
  generateTestScenarioName,
} from './utils/test-helpers';
import { testLogs } from './fixtures/test-logs';
import { newScenarioData } from './fixtures/test-scenarios';

const testScenarioPrefix = 'Compare Test';
let createdScenarioIds: string[] = [];

test.describe('Scenario Comparison', () => {
  test.beforeAll(async ({ request }) => {
    // Create multiple scenarios for comparison
    for (let i = 1; i <= 3; i++) {
      const scenario = await createScenarioViaAPI(request, {
        ...newScenarioData,
        name: generateTestScenarioName(`${testScenarioPrefix} ${i}`),
        region: ['us-east-1', 'eu-west-1', 'ap-southeast-1'][i - 1],
      });
      createdScenarioIds.push(scenario.id);

      // Start and add some logs to make scenarios more realistic
      await startScenarioViaAPI(request, scenario.id);
      await sendTestLogs(request, scenario.id, testLogs.slice(0, i * 2));
    }
  });

  test.afterAll(async ({ request }) => {
    // Cleanup all created scenarios
    for (const scenarioId of createdScenarioIds) {
      try {
        await request.post(`http://localhost:8000/api/v1/scenarios/${scenarioId}/stop`);
      } catch {
        // Scenario might not be running
      }
      await deleteScenarioViaAPI(request, scenarioId);
    }
    createdScenarioIds = [];
  });

  test('should display scenarios list for comparison selection', async ({ page }) => {
    await navigateTo(page, '/scenarios');
    await waitForLoading(page);

    // Verify scenarios page loads
    await expect(page.getByRole('heading', { name: 'Scenarios' })).toBeVisible();

    // Verify table with scenarios is visible
    const table = page.locator('table');
    await expect(table).toBeVisible();

    // Verify at least our test scenarios are visible
    const rows = table.locator('tbody tr');
    await expect(rows).toHaveCount((await rows.count()) >= 3);
  });

  test('should navigate to compare page via API', async ({ page, request }) => {
    // Try to access compare page directly
    const response = await request.post(
      'http://localhost:8000/api/v1/scenarios/compare',
      {
        data: {
          scenario_ids: createdScenarioIds.slice(0, 2),
          metrics: ['total_cost', 'total_requests'],
        },
      }
    );

    if (response.status() === 404) {
      test.skip();
    }

    if (response.ok()) {
      const data = await response.json();
      
      // Verify response structure
      expect(data).toHaveProperty('scenarios');
      expect(data).toHaveProperty('comparison');
      expect(Array.isArray(data.scenarios)).toBe(true);
      expect(data.scenarios.length).toBe(2);
    }
  });

  test('should compare 2 scenarios', async ({ request }) => {
    const response = await request.post(
      'http://localhost:8000/api/v1/scenarios/compare',
      {
        data: {
          scenario_ids: createdScenarioIds.slice(0, 2),
          metrics: ['total_cost', 'total_requests', 'sqs_blocks'],
        },
      }
    );

    if (response.status() === 404) {
      test.skip();
    }

    if (response.ok()) {
      const data = await response.json();
      
      expect(data.scenarios).toHaveLength(2);
      expect(data.comparison).toBeDefined();
    }
  });

  test('should compare 3 scenarios', async ({ request }) => {
    const response = await request.post(
      'http://localhost:8000/api/v1/scenarios/compare',
      {
        data: {
          scenario_ids: createdScenarioIds,
          metrics: ['total_cost', 'total_requests', 'lambda_invocations'],
        },
      }
    );

    if (response.status() === 404) {
      test.skip();
    }

    if (response.ok()) {
      const data = await response.json();
      
      expect(data.scenarios).toHaveLength(3);
      expect(data.comparison).toBeDefined();
    }
  });

  test('should compare 4 scenarios (max allowed)', async ({ request }) => {
    // Create a 4th scenario
    const scenario4 = await createScenarioViaAPI(request, {
      ...newScenarioData,
      name: generateTestScenarioName(`${testScenarioPrefix} 4`),
    });

    try {
      const response = await request.post(
        'http://localhost:8000/api/v1/scenarios/compare',
        {
          data: {
            scenario_ids: [...createdScenarioIds, scenario4.id],
            metrics: ['total_cost'],
          },
        }
      );

      if (response.status() === 404) {
        test.skip();
      }

      if (response.ok()) {
        const data = await response.json();
        expect(data.scenarios).toHaveLength(4);
      }
    } finally {
      await deleteScenarioViaAPI(request, scenario4.id);
    }
  });

  test('should reject comparison with more than 4 scenarios', async ({ request }) => {
    // Create additional scenarios
    const extraScenarios: string[] = [];
    for (let i = 0; i < 2; i++) {
      const scenario = await createScenarioViaAPI(request, {
        ...newScenarioData,
        name: generateTestScenarioName(`${testScenarioPrefix} Extra ${i}`),
      });
      extraScenarios.push(scenario.id);
    }

    try {
      const response = await request.post(
        'http://localhost:8000/api/v1/scenarios/compare',
        {
          data: {
            scenario_ids: [...createdScenarioIds, ...extraScenarios],
            metrics: ['total_cost'],
          },
        }
      );

      if (response.status() === 404) {
        test.skip();
      }

      // Should return 400 for too many scenarios
      expect(response.status()).toBe(400);
    } finally {
      // Cleanup extra scenarios
      for (const id of extraScenarios) {
        await deleteScenarioViaAPI(request, id);
      }
    }
  });

  test('should reject comparison with invalid scenario IDs', async ({ request }) => {
    const response = await request.post(
      'http://localhost:8000/api/v1/scenarios/compare',
      {
        data: {
          scenario_ids: ['invalid-id-1', 'invalid-id-2'],
          metrics: ['total_cost'],
        },
      }
    );

    if (response.status() === 404) {
      test.skip();
    }

    // Should return 400 or 404 for invalid IDs
    expect([400, 404]).toContain(response.status());
  });

  test('should reject comparison with single scenario', async ({ request }) => {
    const response = await request.post(
      'http://localhost:8000/api/v1/scenarios/compare',
      {
        data: {
          scenario_ids: [createdScenarioIds[0]],
          metrics: ['total_cost'],
        },
      }
    );

    if (response.status() === 404) {
      test.skip();
    }

    // Should return 400 for single scenario
    expect(response.status()).toBe(400);
  });

  test('should include delta calculations in comparison', async ({ request }) => {
    const response = await request.post(
      'http://localhost:8000/api/v1/scenarios/compare',
      {
        data: {
          scenario_ids: createdScenarioIds.slice(0, 2),
          metrics: ['total_cost', 'total_requests'],
        },
      }
    );

    if (response.status() === 404) {
      test.skip();
    }

    if (response.ok()) {
      const data = await response.json();
      
      // Verify comparison includes deltas
      expect(data.comparison).toBeDefined();
      
      if (data.comparison.total_cost) {
        expect(data.comparison.total_cost).toHaveProperty('baseline');
        expect(data.comparison.total_cost).toHaveProperty('variance');
      }
    }
  });

  test('should support comparison export', async ({ request }) => {
    const response = await request.post(
      'http://localhost:8000/api/v1/scenarios/compare',
      {
        data: {
          scenario_ids: createdScenarioIds.slice(0, 2),
          metrics: ['total_cost', 'total_requests'],
        },
      }
    );

    if (response.status() === 404) {
      test.skip();
    }

    if (response.ok()) {
      // If compare API exists, check if export is available
      const exportResponse = await request.get(
        `http://localhost:8000/api/v1/scenarios/compare/export?ids=${createdScenarioIds.slice(0, 2).join(',')}&format=csv`
      );

      // Export might not exist yet
      if (exportResponse.status() !== 404) {
        expect(exportResponse.ok()).toBeTruthy();
      }
    }
  });
});

test.describe('Comparison UI Tests', () => {
  test('should navigate to compare page from sidebar', async ({ page }) => {
    await navigateTo(page, '/');
    await waitForLoading(page);

    // Verify dashboard loads
    await expect(page.getByRole('heading', { name: 'Dashboard' })).toBeVisible();

    // Try to navigate to compare page (if it exists)
    const compareResponse = await page.request.get('http://localhost:5173/compare');
    
    if (compareResponse.status() === 200) {
      await navigateTo(page, '/compare');
      await waitForLoading(page);
      
      // Verify compare page elements
      await expect(page.locator('body')).toBeVisible();
    }
  });

  test('should display scenarios in comparison view', async ({ page }) => {
    // Navigate to scenarios page
    await navigateTo(page, '/scenarios');
    await waitForLoading(page);

    // Verify scenarios are listed
    const table = page.locator('table tbody');
    await expect(table).toBeVisible();

    // Verify table has rows
    const rows = table.locator('tr');
    const rowCount = await rows.count();
    expect(rowCount).toBeGreaterThan(0);
  });

  test('should show comparison metrics table', async ({ page }) => {
    await navigateTo(page, '/scenarios');
    await waitForLoading(page);

    // Verify metrics columns exist
    await expect(page.getByRole('columnheader', { name: /requests/i })).toBeVisible();
    await expect(page.getByRole('columnheader', { name: /cost/i })).toBeVisible();
  });

  test('should highlight best/worst performers', async ({ page }) => {
    // This test verifies the UI elements exist for comparison highlighting
    await navigateTo(page, '/scenarios');
    await waitForLoading(page);

    // Verify table with color-coded status exists
    const table = page.locator('table');
    await expect(table).toBeVisible();
  });
});

test.describe('Comparison Performance', () => {
  test('should load comparison data within acceptable time', async ({ request }) => {
    const startTime = Date.now();
    
    const response = await request.post(
      'http://localhost:8000/api/v1/scenarios/compare',
      {
        data: {
          scenario_ids: createdScenarioIds.slice(0, 2),
          metrics: ['total_cost', 'total_requests'],
        },
      }
    );

    const duration = Date.now() - startTime;

    if (response.status() === 404) {
      test.skip();
    }

    // Should complete within 5 seconds
    expect(duration).toBeLessThan(5000);
  });

  test('should cache comparison results', async ({ request }) => {
    const requestBody = {
      scenario_ids: createdScenarioIds.slice(0, 2),
      metrics: ['total_cost'],
    };

    // First request
    const response1 = await request.post(
      'http://localhost:8000/api/v1/scenarios/compare',
      { data: requestBody }
    );

    if (response1.status() === 404) {
      test.skip();
    }

    // Second identical request (should be cached)
    const startTime = Date.now();
    const response2 = await request.post(
      'http://localhost:8000/api/v1/scenarios/compare',
      { data: requestBody }
    );
    const duration = Date.now() - startTime;

    // Cached response should be very fast
    if (response2.ok()) {
      expect(duration).toBeLessThan(1000);
    }
  });
});
