import { test, expect, type Page } from '@playwright/test';
import {
  TEST_CONFIG,
  loginAsUser,
  setupErrorCapture,
  navigateViaHref,
} from './utils/test-helpers';

/**
 * Navigation E2E Test Suite
 * 
 * Tests the complete navigation flow of the application:
 * - Sidebar navigation
 * - Route guards (protected routes)
 * - Deep linking
 * - Browser back/forward navigation
 * - Active route highlighting
 * - Mobile navigation (responsive)
 */

test.describe('Navigation Flow', () => {
  let consoleErrors: string[] = [];
  let networkErrors: Array<{ url: string; status: number; method: string }> = [];

  test.beforeEach(async ({ page }) => {
    const errorCapture = setupErrorCapture(page);
    consoleErrors = errorCapture.consoleErrors;
    networkErrors = errorCapture.networkErrors;
  });

  test.describe('Authenticated Navigation', () => {
    test.beforeEach(async ({ page }) => {
      await loginAsUser(page);
    });

    test('should navigate to dashboard from sidebar', async ({ page }) => {
      await page.goto(`${TEST_CONFIG.FRONTEND_URL}/library`);
      await page.waitForLoadState('networkidle');

      // Click dashboard link in sidebar
      const dashboardLink = page.locator('nav a[href="/dashboard"], nav a[href="/"]').first();
      await expect(dashboardLink).toBeVisible();
      await dashboardLink.click();

      await expect(page).toHaveURL(new RegExp(`${TEST_CONFIG.FRONTEND_URL}/?(dashboard)?$`));
    });

    test('should navigate to library from sidebar', async ({ page }) => {
      await page.goto(`${TEST_CONFIG.FRONTEND_URL}/dashboard`);
      await page.waitForLoadState('networkidle');

      const libraryLink = page.locator('nav a[href="/library"]').first();
      await expect(libraryLink).toBeVisible();
      await libraryLink.click();

      await expect(page).toHaveURL(new RegExp(`${TEST_CONFIG.FRONTEND_URL}/library`));
    });

    test('should navigate to playlists from sidebar', async ({ page }) => {
      await page.goto(`${TEST_CONFIG.FRONTEND_URL}/dashboard`);
      await page.waitForLoadState('networkidle');

      const playlistsLink = page.locator('nav a[href="/playlists"]').first();
      await expect(playlistsLink).toBeVisible();
      await playlistsLink.click();

      await expect(page).toHaveURL(new RegExp(`${TEST_CONFIG.FRONTEND_URL}/playlists`));
    });

    test('should navigate to profile from sidebar', async ({ page }) => {
      await page.goto(`${TEST_CONFIG.FRONTEND_URL}/dashboard`);
      await page.waitForLoadState('networkidle');

      // Profile link might be in a dropdown menu
      const profileLink = page.locator('nav a[href*="/profile"], nav a[href*="/user"]').first();
      if (await profileLink.isVisible({ timeout: 2000 }).catch(() => false)) {
        await profileLink.click();
        await expect(page).toHaveURL(new RegExp(`${TEST_CONFIG.FRONTEND_URL}/(profile|user)`));
      } else {
        // Try clicking avatar/user menu first
        const userMenu = page.locator('button[aria-label*="user"], button[aria-label*="menu"], [data-testid="user-menu"]').first();
        if (await userMenu.isVisible({ timeout: 2000 }).catch(() => false)) {
          await userMenu.click();
          const profileLinkInMenu = page.locator('a[href*="/profile"], a[href*="/user"]').first();
          await expect(profileLinkInMenu).toBeVisible({ timeout: 5000 });
          await profileLinkInMenu.click();
          await expect(page).toHaveURL(new RegExp(`${TEST_CONFIG.FRONTEND_URL}/(profile|user)`));
        }
      }
    });

    test('should highlight active route in sidebar', async ({ page }) => {
      await page.goto(`${TEST_CONFIG.FRONTEND_URL}/library`);
      await page.waitForLoadState('networkidle');

      // Check if library link has active state
      const libraryLink = page.locator('nav a[href="/library"]').first();
      const isActive = await libraryLink.evaluate((el) => {
        return el.classList.contains('active') || 
               el.getAttribute('aria-current') === 'page' ||
               el.closest('[aria-current="page"]') !== null;
      });

      // Some apps use different active indicators, so we just check it's visible
      await expect(libraryLink).toBeVisible();
    });

    test('should support browser back navigation', async ({ page }) => {
      await page.goto(`${TEST_CONFIG.FRONTEND_URL}/dashboard`);
      await page.waitForLoadState('networkidle');

      // Navigate to library
      await page.goto(`${TEST_CONFIG.FRONTEND_URL}/library`);
      await page.waitForLoadState('networkidle');
      await expect(page).toHaveURL(new RegExp(`${TEST_CONFIG.FRONTEND_URL}/library`));

      // Go back
      await page.goBack();
      await page.waitForLoadState('networkidle');
      
      // Should be back on dashboard (or previous page)
      const currentUrl = page.url();
      expect(currentUrl).toMatch(new RegExp(`${TEST_CONFIG.FRONTEND_URL}/(dashboard|library)?`));
    });

    test('should support browser forward navigation', async ({ page }) => {
      await page.goto(`${TEST_CONFIG.FRONTEND_URL}/dashboard`);
      await page.waitForLoadState('networkidle');

      // Navigate to library
      await page.goto(`${TEST_CONFIG.FRONTEND_URL}/library`);
      await page.waitForLoadState('networkidle');

      // Go back
      await page.goBack();
      await page.waitForLoadState('networkidle');

      // Go forward
      await page.goForward();
      await page.waitForLoadState('networkidle');
      await expect(page).toHaveURL(new RegExp(`${TEST_CONFIG.FRONTEND_URL}/library`));
    });

    test('should support deep linking to protected routes', async ({ page }) => {
      // Direct navigation to a protected route
      await page.goto(`${TEST_CONFIG.FRONTEND_URL}/library`);
      await page.waitForLoadState('networkidle');

      // Should be able to access the route (already authenticated)
      await expect(page).toHaveURL(new RegExp(`${TEST_CONFIG.FRONTEND_URL}/library`));
      
      // Page should be loaded (not showing login)
      const loginForm = page.locator('form[action*="login"], input[type="email"]');
      await expect(loginForm).not.toBeVisible({ timeout: 2000 });
    });
  });

  test.describe('Unauthenticated Navigation', () => {
    // Reset storage state to ensure we're not authenticated
    test.use({ storageState: { cookies: [], origins: [] } });

    test('should redirect to login when accessing protected route', async ({ page }) => {
      await page.goto(`${TEST_CONFIG.FRONTEND_URL}/library`);
      await page.waitForLoadState('networkidle');

      // Should redirect to login
      await expect(page).toHaveURL(new RegExp(`${TEST_CONFIG.FRONTEND_URL}/(login|auth/login)`));
    });

    test('should allow access to public routes', async ({ page }) => {
      // Try to access login page
      await page.goto(`${TEST_CONFIG.FRONTEND_URL}/login`);
      await page.waitForLoadState('networkidle');

      // Should be on login page
      const loginForm = page.locator('form[action*="login"], input[type="email"]').first();
      await expect(loginForm).toBeVisible({ timeout: 5000 });
    });

    test('should allow access to register page', async ({ page }) => {
      await page.goto(`${TEST_CONFIG.FRONTEND_URL}/register`);
      await page.waitForLoadState('networkidle');

      // Should be on register page
      const registerForm = page.locator('form[action*="register"], input[name*="email"]').first();
      await expect(registerForm).toBeVisible({ timeout: 5000 });
    });
  });

  test.describe('Mobile Navigation', () => {
    test.beforeEach(async ({ page }) => {
      await loginAsUser(page);
      // Set mobile viewport
      await page.setViewportSize({ width: 375, height: 667 });
    });

    test('should show mobile menu when hamburger is clicked', async ({ page }) => {
      await page.goto(`${TEST_CONFIG.FRONTEND_URL}/dashboard`);
      await page.waitForLoadState('networkidle');

      // Look for hamburger menu button
      const hamburgerButton = page.locator('button[aria-label*="menu"], button[aria-label*="navigation"], [data-testid="mobile-menu-button"]').first();
      
      if (await hamburgerButton.isVisible({ timeout: 2000 }).catch(() => false)) {
        await hamburgerButton.click();
        
        // Menu should be visible
        const mobileMenu = page.locator('nav[aria-label*="mobile"], nav[data-testid="mobile-nav"]').first();
        await expect(mobileMenu).toBeVisible({ timeout: 3000 });
      } else {
        // Mobile menu might not be implemented, skip test
        test.skip();
      }
    });

    test('should navigate from mobile menu', async ({ page }) => {
      await page.goto(`${TEST_CONFIG.FRONTEND_URL}/dashboard`);
      await page.waitForLoadState('networkidle');

      const hamburgerButton = page.locator('button[aria-label*="menu"], button[aria-label*="navigation"]').first();
      
      if (await hamburgerButton.isVisible({ timeout: 2000 }).catch(() => false)) {
        await hamburgerButton.click();
        
        // Click library link in mobile menu
        const libraryLink = page.locator('nav a[href="/library"]').first();
        await expect(libraryLink).toBeVisible({ timeout: 3000 });
        await libraryLink.click();
        
        await expect(page).toHaveURL(new RegExp(`${TEST_CONFIG.FRONTEND_URL}/library`));
      } else {
        test.skip();
      }
    });
  });

  test.describe('Error Handling', () => {
    test.beforeEach(async ({ page }) => {
      await loginAsUser(page);
    });

    test('should handle 404 pages gracefully', async ({ page }) => {
      await page.goto(`${TEST_CONFIG.FRONTEND_URL}/non-existent-page-12345`);
      await page.waitForLoadState('networkidle');

      // Should show 404 page or redirect to dashboard
      const currentUrl = page.url();
      const has404Content = await page.locator('text=404, text=Not Found, text=Page not found').first().isVisible({ timeout: 2000 }).catch(() => false);
      const redirectedToDashboard = currentUrl.includes('/dashboard') || currentUrl === `${TEST_CONFIG.FRONTEND_URL  }/`;

      expect(has404Content || redirectedToDashboard).toBeTruthy();
    });

    test('should handle navigation errors gracefully', async ({ page }) => {
      // Intercept navigation and simulate error
      await page.route('**/api/**', (route) => {
        if (route.request().url().includes('/library')) {
          route.abort('failed');
        } else {
          route.continue();
        }
      });

      await page.goto(`${TEST_CONFIG.FRONTEND_URL}/dashboard`);
      await page.waitForLoadState('networkidle');

      // Try to navigate to library (should handle error)
      const libraryLink = page.locator('nav a[href="/library"]').first();
      if (await libraryLink.isVisible({ timeout: 2000 }).catch(() => false)) {
        await libraryLink.click();
        
        // Should show error message or stay on current page
        await page.waitForTimeout(2000);
        const errorToast = page.locator('text=error, text=Error, text=failed').first();
        const stillOnDashboard = page.url().includes('/dashboard');
        
        // Either error is shown or we're still on dashboard
        expect(await errorToast.isVisible({ timeout: 2000 }).catch(() => false) || stillOnDashboard).toBeTruthy();
      }
    });
  });
});

