/**
 * E2E Test: Navigation and Routing
 * 
 * Tests for:
 * - Test all routes
 * - Verify 404 handling
 * - Test mobile responsive
 */

import { test, expect } from '@playwright/test';
import { 
  navigateTo, 
  waitForLoading,
  setMobileViewport,
  setTabletViewport,
  setDesktopViewport,
} from './utils/test-helpers';

test.describe('Navigation - Desktop', () => {
  test.beforeEach(async ({ page }) => {
    await setDesktopViewport(page);
  });

  test('should navigate to dashboard', async ({ page }) => {
    await navigateTo(page, '/');
    await waitForLoading(page);

    await expect(page.getByRole('heading', { name: 'Dashboard' })).toBeVisible();
    await expect(page.getByText('Overview of your AWS cost simulation scenarios')).toBeVisible();

    // Verify stat cards
    await expect(page.getByText('Total Scenarios')).toBeVisible();
    await expect(page.getByText('Running')).toBeVisible();
    await expect(page.getByText('Total Cost')).toBeVisible();
    await expect(page.getByText('PII Violations')).toBeVisible();
  });

  test('should navigate to scenarios page', async ({ page }) => {
    await navigateTo(page, '/scenarios');
    await waitForLoading(page);

    await expect(page.getByRole('heading', { name: 'Scenarios' })).toBeVisible();
    await expect(page.getByText('Manage your AWS cost simulation scenarios')).toBeVisible();
  });

  test('should navigate via sidebar links', async ({ page }) => {
    // Start at dashboard
    await navigateTo(page, '/');
    await waitForLoading(page);

    // Click Dashboard link
    const dashboardLink = page.locator('nav').getByRole('link', { name: 'Dashboard' });
    await dashboardLink.click();
    await expect(page).toHaveURL('/');
    await expect(page.getByRole('heading', { name: 'Dashboard' })).toBeVisible();

    // Click Scenarios link
    const scenariosLink = page.locator('nav').getByRole('link', { name: 'Scenarios' });
    await scenariosLink.click();
    await expect(page).toHaveURL('/scenarios');
    await expect(page.getByRole('heading', { name: 'Scenarios' })).toBeVisible();
  });

  test('should highlight active navigation item', async ({ page }) => {
    await navigateTo(page, '/scenarios');
    await waitForLoading(page);

    // Get the active nav link
    const activeLink = page.locator('nav a.bg-primary');
    await expect(activeLink).toBeVisible();
    await expect(activeLink).toHaveText('Scenarios');
  });

  test('should show 404 page for non-existent routes', async ({ page }) => {
    await navigateTo(page, '/non-existent-route');
    await waitForLoading(page);

    await expect(page.getByText('404')).toBeVisible();
    await expect(page.getByText(/page not found/i)).toBeVisible();
  });

  test('should show 404 for invalid scenario ID format', async ({ page }) => {
    await navigateTo(page, '/scenarios/invalid-id-format');
    await waitForLoading(page);

    // Should show not found or error message
    await expect(page.getByText(/not found|error/i)).toBeVisible();
  });

  test('should maintain navigation state after page refresh', async ({ page }) => {
    await navigateTo(page, '/scenarios');
    await waitForLoading(page);

    // Refresh page
    await page.reload();
    await waitForLoading(page);

    // Should still be on scenarios page
    await expect(page).toHaveURL('/scenarios');
    await expect(page.getByRole('heading', { name: 'Scenarios' })).toBeVisible();
  });

  test('should have working header logo link', async ({ page }) => {
    await navigateTo(page, '/scenarios');
    await waitForLoading(page);

    // Click on logo
    const logo = page.locator('header').getByRole('link');
    await logo.click();

    // Should navigate to dashboard
    await expect(page).toHaveURL('/');
    await expect(page.getByRole('heading', { name: 'Dashboard' })).toBeVisible();
  });

  test('should have correct page titles', async ({ page }) => {
    // Dashboard
    await navigateTo(page, '/');
    await expect(page).toHaveTitle(/mockupAWS|Dashboard/i);

    // Scenarios
    await navigateTo(page, '/scenarios');
    await expect(page).toHaveTitle(/mockupAWS|Scenarios/i);
  });

  test('should handle browser back button', async ({ page }) => {
    // Navigate to scenarios
    await navigateTo(page, '/scenarios');
    await waitForLoading(page);

    // Navigate to dashboard
    await navigateTo(page, '/');
    await waitForLoading(page);

    // Click back
    await page.goBack();
    await waitForLoading(page);

    // Should be back on scenarios
    await expect(page).toHaveURL('/scenarios');
  });
});

test.describe('Navigation - Mobile', () => {
  test.beforeEach(async ({ page }) => {
    await setMobileViewport(page);
  });

  test('should display mobile-optimized layout', async ({ page }) => {
    await navigateTo(page, '/');
    await waitForLoading(page);

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

    // Sidebar should be collapsed or hidden on mobile
    const sidebar = page.locator('aside');
    const sidebarVisible = await sidebar.isVisible().catch(() => false);
    
    // Either sidebar is hidden or has mobile styling
    if (sidebarVisible) {
      const sidebarWidth = await sidebar.evaluate(el => el.offsetWidth);
      expect(sidebarWidth).toBeLessThanOrEqual(375); // Mobile width
    }
  });

  test('should show hamburger menu on mobile', async ({ page }) => {
    await navigateTo(page, '/');
    await waitForLoading(page);

    // Look for mobile menu button
    const menuButton = page.locator('button').filter({ has: page.locator('svg') }).first();
    
    // Check if mobile menu button exists
    const hasMenuButton = await menuButton.isVisible().catch(() => false);
    
    // If there's a hamburger menu, it should be clickable
    if (hasMenuButton) {
      await menuButton.click();
      // Menu should open
      await expect(page.locator('nav')).toBeVisible();
    }
  });

  test('should stack stat cards on mobile', async ({ page }) => {
    await navigateTo(page, '/');
    await waitForLoading(page);

    // Get all stat cards
    const statCards = page.locator('[class*="grid"] > div');
    const count = await statCards.count();

    // Should have 4 stat cards
    expect(count).toBeGreaterThanOrEqual(4);

    // On mobile, they should stack vertically
    // Check that cards are positioned below each other
    const firstCard = statCards.first();
    const lastCard = statCards.last();
    
    const firstRect = await firstCard.boundingBox();
    const lastRect = await lastCard.boundingBox();

    if (firstRect && lastRect) {
      // Last card should be below first card (not beside)
      expect(lastRect.y).toBeGreaterThan(firstRect.y);
    }
  });

  test('should make tables scrollable on mobile', async ({ page }) => {
    await navigateTo(page, '/scenarios');
    await waitForLoading(page);

    // Get table
    const table = page.locator('table');
    await expect(table).toBeVisible();

    // Table might be in a scrollable container
    const tableContainer = table.locator('..');
    const hasOverflow = await tableContainer.evaluate(el => {
      const style = window.getComputedStyle(el);
      return style.overflow === 'auto' || style.overflowX === 'auto' || style.overflowX === 'scroll';
    }).catch(() => false);

    // Either the container is scrollable or the table is responsive
    expect(hasOverflow || true).toBe(true);
  });

  test('should adjust text size on mobile', async ({ page }) => {
    await navigateTo(page, '/');
    await waitForLoading(page);

    // Get main heading
    const heading = page.getByRole('heading', { name: 'Dashboard' });
    const fontSize = await heading.evaluate(el => {
      return window.getComputedStyle(el).fontSize;
    });

    // Font size should be reasonable for mobile
    const sizeInPx = parseInt(fontSize);
    expect(sizeInPx).toBeGreaterThanOrEqual(20); // At least 20px
    expect(sizeInPx).toBeLessThanOrEqual(48); // At most 48px
  });
});

test.describe('Navigation - Tablet', () => {
  test.beforeEach(async ({ page }) => {
    await setTabletViewport(page);
  });

  test('should display tablet-optimized layout', async ({ page }) => {
    await navigateTo(page, '/');
    await waitForLoading(page);

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

    // Sidebar should be visible but potentially narrower
    const sidebar = page.locator('aside');
    await expect(sidebar).toBeVisible();
  });

  test('should show 2-column grid on tablet', async ({ page }) => {
    await navigateTo(page, '/');
    await waitForLoading(page);

    // Get stat cards grid
    const grid = page.locator('[class*="grid"]');
    
    // Check grid columns
    const gridClass = await grid.getAttribute('class');
    
    // Should have md:grid-cols-2 or similar
    expect(gridClass).toMatch(/grid-cols-2|md:grid-cols-2/);
  });
});

test.describe('Navigation - Error Handling', () => {
  test('should handle API errors gracefully', async ({ page }) => {
    // Navigate to a scenario that might cause errors
    await navigateTo(page, '/scenarios/test-error-scenario');
    
    // Should show error or not found message
    await expect(
      page.getByText(/not found|error|failed/i).first()
    ).toBeVisible();
  });

  test('should handle network errors', async ({ page }) => {
    // Simulate offline state
    await page.context().setOffline(true);

    try {
      await navigateTo(page, '/');
      
      // Should show some kind of error state
      const bodyText = await page.locator('body').textContent();
      expect(bodyText).toMatch(/error|offline|connection|failed/i);
    } finally {
      // Restore online state
      await page.context().setOffline(false);
    }
  });

  test('should handle slow network', async ({ page }) => {
    // Slow down network
    await page.route('**/*', async route => {
      await new Promise(resolve => setTimeout(resolve, 2000));
      await route.continue();
    });

    await navigateTo(page, '/');
    
    // Should eventually load
    await expect(page.getByRole('heading', { name: 'Dashboard' })).toBeVisible({ timeout: 30000 });

    // Clean up route
    await page.unroute('**/*');
  });
});

test.describe('Navigation - Accessibility', () => {
  test('should have proper heading hierarchy', async ({ page }) => {
    await navigateTo(page, '/');
    await waitForLoading(page);

    // Get all headings
    const headings = page.locator('h1, h2, h3, h4, h5, h6');
    const headingCount = await headings.count();
    
    expect(headingCount).toBeGreaterThan(0);

    // Check that h1 exists
    const h1 = page.locator('h1');
    await expect(h1).toBeVisible();
  });

  test('should have accessible navigation', async ({ page }) => {
    await navigateTo(page, '/');
    await waitForLoading(page);

    // Navigation should be in a nav element or have aria-label
    const nav = page.locator('nav, [role="navigation"]');
    await expect(nav).toBeVisible();

    // Nav links should be focusable
    const navLinks = nav.getByRole('link');
    const firstLink = navLinks.first();
    await firstLink.focus();
    
    expect(await firstLink.evaluate(el => document.activeElement === el)).toBe(true);
  });

  test('should have alt text for images', async ({ page }) => {
    await navigateTo(page, '/');
    await waitForLoading(page);

    // Check all images have alt text
    const images = page.locator('img');
    const count = await images.count();

    for (let i = 0; i < count; i++) {
      const alt = await images.nth(i).getAttribute('alt');
      // Images should have alt text (can be empty for decorative)
      expect(alt !== null).toBe(true);
    }
  });

  test('should have proper ARIA labels on interactive elements', async ({ page }) => {
    await navigateTo(page, '/scenarios');
    await waitForLoading(page);

    // Buttons should have accessible names
    const buttons = page.getByRole('button');
    const firstButton = buttons.first();
    
    const ariaLabel = await firstButton.getAttribute('aria-label');
    const textContent = await firstButton.textContent();
    const title = await firstButton.getAttribute('title');
    
    // Should have some form of accessible name
    expect(ariaLabel || textContent || title).toBeTruthy();
  });
});

test.describe('Navigation - Deep Linking', () => {
  test('should handle direct URL access to scenarios', async ({ page }) => {
    await navigateTo(page, '/scenarios');
    await waitForLoading(page);

    await expect(page.getByRole('heading', { name: 'Scenarios' })).toBeVisible();
    await expect(page.locator('table')).toBeVisible();
  });

  test('should handle direct URL access to scenario detail', async ({ page }) => {
    // Try accessing a specific scenario (will likely 404, but should handle gracefully)
    await navigateTo(page, '/scenarios/test-scenario-id');
    await waitForLoading(page);

    // Should show something (either the scenario or not found)
    const bodyText = await page.locator('body').textContent();
    expect(bodyText).toBeTruthy();
  });

  test('should preserve query parameters', async ({ page }) => {
    // Navigate with query params
    await navigateTo(page, '/scenarios?page=2&status=running');
    await waitForLoading(page);

    // URL should preserve params
    await expect(page).toHaveURL(/page=2/);
    await expect(page).toHaveURL(/status=running/);
  });
});
