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

test.describe('Leptos Components - Comprehensive E2E Testing', () => {
  test.beforeEach(async ({ page }) => {
    // Navigate to Leptos example app
    await page.goto('/');
    // Wait for the app to be fully loaded
    await page.waitForLoadState('networkidle');
  });

  test.describe('Core UI Components', () => {
    test('button component - basic functionality and variants', async ({ page }) => {
      // Test different button variants
      const buttons = page.locator('button');
      await expect(buttons).toHaveCount(await buttons.count());
      
      // Test primary button
      const primaryButton = page.locator('button').filter({ hasText: /primary|default|submit/i }).first();
      if (await primaryButton.isVisible()) {
        await expect(primaryButton).toBeVisible();
        await primaryButton.click();
        // Verify button state changes
        await expect(primaryButton).toBeEnabled();
      }
    });

    test('input component - user interaction and validation', async ({ page }) => {
      const inputs = page.locator('input[type="text"], input[type="email"], input[type="password"]');
      
      if (await inputs.count() > 0) {
        const input = inputs.first();
        await expect(input).toBeVisible();
        
        // Test typing
        await input.fill('Test input value');
        await expect(input).toHaveValue('Test input value');
        
        // Test clearing
        await input.clear();
        await expect(input).toHaveValue('');
      }
    });

    test('label component - accessibility and association', async ({ page }) => {
      const labels = page.locator('label');
      
      if (await labels.count() > 0) {
        for (let i = 0; i < await labels.count(); i++) {
          const label = labels.nth(i);
          await expect(label).toBeVisible();
          
          // Check if label has proper text content
          const text = await label.textContent();
          expect(text).toBeTruthy();
          expect(text!.trim().length).toBeGreaterThan(0);
        }
      }
    });

    test('card component - structure, styling, and responsiveness', async ({ page }) => {
      const cards = page.locator('[class*="card"], .card, [class*="rounded"], [class*="border"]');
      
      if (await cards.count() > 0) {
        const card = cards.first();
        await expect(card).toBeVisible();
        
        // Test responsive behavior
        await page.setViewportSize({ width: 320, height: 568 }); // Mobile
        await expect(card).toBeVisible();
        
        await page.setViewportSize({ width: 1280, height: 720 }); // Desktop
        await expect(card).toBeVisible();
      }
    });

    test('badge component - display and variants', async ({ page }) => {
      const badges = page.locator('[class*="badge"], .badge, [class*="inline-flex"], [class*="rounded-full"]');
      
      if (await badges.count() > 0) {
        for (let i = 0; i < await badges.count(); i++) {
          const badge = badges.nth(i);
          await expect(badge).toBeVisible();
          
          // Check badge content
          const text = await badge.textContent();
          expect(text).toBeTruthy();
        }
      }
    });

    test('checkbox component - interaction and state', async ({ page }) => {
      const checkboxes = page.locator('input[type="checkbox"]');
      
      if (await checkboxes.count() > 0) {
        const checkbox = checkboxes.first();
        await expect(checkbox).toBeVisible();
        
        // Test checkbox interaction
        const initialChecked = await checkbox.isChecked();
        await checkbox.click();
        const afterClickChecked = await checkbox.isChecked();
        
        // State should change
        expect(afterClickChecked).toBe(!initialChecked);
      }
    });
  });

  test.describe('Layout and Navigation Components', () => {
    test('separator component - visual separation', async ({ page }) => {
      const separators = page.locator('hr, [class*="separator"], [class*="border-t"], [class*="border-b"]');
      
      if (await separators.count() > 0) {
        const separator = separators.first();
        await expect(separator).toBeVisible();
        
        // Check if separator has proper styling
        const classes = await separator.getAttribute('class');
        expect(classes).toBeTruthy();
      }
    });

    test('navigation-menu component - menu structure and interaction', async ({ page }) => {
      const navMenus = page.locator('nav, [class*="navigation"], [class*="menu"]');
      
      if (await navMenus.count() > 0) {
        const nav = navMenus.first();
        await expect(nav).toBeVisible();
        
        // Test navigation items
        const navItems = nav.locator('a, button, [role="menuitem"]');
        if (await navItems.count() > 0) {
          await expect(navItems.first()).toBeVisible();
        }
      }
    });

    test('breadcrumb component - navigation path', async ({ page }) => {
      const breadcrumbs = page.locator('[class*="breadcrumb"], .breadcrumb, nav[aria-label*="breadcrumb"]');
      
      if (await breadcrumbs.count() > 0) {
        const breadcrumb = breadcrumbs.first();
        await expect(breadcrumb).toBeVisible();
        
        // Check breadcrumb items
        const items = breadcrumb.locator('a, span, [class*="breadcrumb-item"]');
        if (await items.count() > 0) {
          await expect(items.first()).toBeVisible();
        }
      }
    });

    test('pagination component - page navigation', async ({ page }) => {
      const paginations = page.locator('[class*="pagination"], .pagination, nav[aria-label*="pagination"]');
      
      if (await paginations.count() > 0) {
        const pagination = paginations.first();
        await expect(pagination).toBeVisible();
        
        // Check pagination controls
        const controls = pagination.locator('button, a, [class*="page"]');
        if (await controls.count() > 0) {
          await expect(controls.first()).toBeVisible();
        }
      }
    });
  });

  test.describe('Interactive Components', () => {
    test('dialog component - modal functionality', async ({ page }) => {
      const dialogTriggers = page.locator('button[aria-haspopup="dialog"], [data-state="closed"]');
      
      if (await dialogTriggers.count() > 0) {
        const trigger = dialogTriggers.first();
        await expect(trigger).toBeVisible();
        
        // Test dialog opening
        await trigger.click();
        
        // Look for dialog content
        const dialog = page.locator('[role="dialog"], [data-state="open"]');
        if (await dialog.count() > 0) {
          await expect(dialog.first()).toBeVisible();
        }
      }
    });

    test('dropdown-menu component - menu expansion', async ({ page }) => {
      const dropdownTriggers = page.locator('button[aria-haspopup="true"], [data-state="closed"]');
      
      if (await dropdownTriggers.count() > 0) {
        const trigger = dropdownTriggers.first();
        await expect(trigger).toBeVisible();
        
        // Test dropdown opening
        await trigger.click();
        
        // Look for dropdown content
        const dropdown = page.locator('[role="menu"], [data-state="open"]');
        if (await dropdown.count() > 0) {
          await expect(dropdown.first()).toBeVisible();
        }
      }
    });

    test('select component - option selection', async ({ page }) => {
      const selects = page.locator('select, [role="combobox"], [class*="select"]');
      
      if (await selects.count() > 0) {
        const select = selects.first();
        await expect(select).toBeVisible();
        
        // Test select interaction
        await select.click();
        
        // Look for options
        const options = page.locator('[role="option"], option');
        if (await options.count() > 0) {
          await expect(options.first()).toBeVisible();
        }
      }
    });

    test('combobox component - search and selection', async ({ page }) => {
      const comboboxes = page.locator('[class*="combobox"], [role="combobox"]');
      
      if (await comboboxes.count() > 0) {
        const combobox = comboboxes.first();
        await expect(combobox).toBeVisible();
        
        // Test input functionality
        const input = combobox.locator('input');
        if (await input.count() > 0) {
          await input.first().fill('test');
          await expect(input.first()).toHaveValue('test');
        }
      }
    });
  });

  test.describe('Form Components', () => {
    test('form component - structure and validation', async ({ page }) => {
      const forms = page.locator('form, [class*="form"]');
      
      if (await forms.count() > 0) {
        const form = forms.first();
        await expect(form).toBeVisible();
        
        // Check form elements
        const formElements = form.locator('input, select, textarea, button');
        if (await formElements.count() > 0) {
          await expect(formElements.first()).toBeVisible();
        }
      }
    });

    test('textarea component - multi-line input', async ({ page }) => {
      const textareas = page.locator('textarea, [class*="textarea"]');
      
      if (await textareas.count() > 0) {
        const textarea = textareas.first();
        await expect(textarea).toBeVisible();
        
        // Test textarea input
        await textarea.fill('Multi-line\ntest input');
        await expect(textarea).toHaveValue('Multi-line\ntest input');
      }
    });

    test('input-otp component - one-time password input', async ({ page }) => {
      const otpInputs = page.locator('[class*="otp"], [class*="input-otp"], input[inputmode="numeric"]');
      
      if (await otpInputs.count() > 0) {
        const otpInput = otpInputs.first();
        await expect(otpInput).toBeVisible();
        
        // Test numeric input
        await otpInput.fill('1234');
        await expect(otpInput).toHaveValue('1234');
      }
    });
  });

  test.describe('Data Display Components', () => {
    test('table component - data presentation', async ({ page }) => {
      const tables = page.locator('table, [class*="table"]');
      
      if (await tables.count() > 0) {
        const table = tables.first();
        await expect(table).toBeVisible();
        
        // Check table structure
        const rows = table.locator('tr');
        if (await rows.count() > 0) {
          await expect(rows.first()).toBeVisible();
        }
      }
    });

    test('calendar component - date display', async ({ page }) => {
      const calendars = page.locator('[class*="calendar"], [class*="date-picker"]');
      
      if (await calendars.count() > 0) {
        const calendar = calendars.first();
        await expect(calendar).toBeVisible();
        
        // Check calendar structure
        const days = calendar.locator('[class*="day"], [class*="date"]');
        if (await days.count() > 0) {
          await expect(days.first()).toBeVisible();
        }
      }
    });

    test('progress component - loading indicators', async ({ page }) => {
      const progressBars = page.locator('[class*="progress"], progress, [role="progressbar"]');
      
      if (await progressBars.count() > 0) {
        const progress = progressBars.first();
        await expect(progress).toBeVisible();
        
        // Check progress attributes
        const value = await progress.getAttribute('value');
        const max = await progress.getAttribute('max');
        expect(value || max).toBeTruthy();
      }
    });
  });

  test.describe('Feedback Components', () => {
    test('alert component - notification display', async ({ page }) => {
      const alerts = page.locator('[class*="alert"], .alert, [role="alert"]');
      
      if (await alerts.count() > 0) {
        const alert = alerts.first();
        await expect(alert).toBeVisible();
        
        // Check alert content
        const text = await alert.textContent();
        expect(text).toBeTruthy();
      }
    });

    test('toast component - temporary notifications', async ({ page }) => {
      const toasts = page.locator('[class*="toast"], .toast, [role="status"]');
      
      if (await toasts.count() > 0) {
        const toast = toasts.first();
        await expect(toast).toBeVisible();
        
        // Check toast content
        const text = await toast.textContent();
        expect(text).toBeTruthy();
      }
    });

    test('tooltip component - hover information', async ({ page }) => {
      const tooltipTriggers = page.locator('[data-tooltip], [title], [aria-describedby]');
      
      if (await tooltipTriggers.count() > 0) {
        const trigger = tooltipTriggers.first();
        await expect(trigger).toBeVisible();
        
        // Test tooltip hover
        await trigger.hover();
        
        // Look for tooltip content
        const tooltip = page.locator('[role="tooltip"], [class*="tooltip"]');
        if (await tooltip.count() > 0) {
          await expect(tooltip.first()).toBeVisible();
        }
      }
    });
  });

  test.describe('Accessibility and Performance', () => {
    test('keyboard navigation - tab order and focus', async ({ page }) => {
      // Test tab navigation
      await page.keyboard.press('Tab');
      const focusedElement = page.locator(':focus');
      await expect(focusedElement).toBeVisible();
      
      // Test multiple tab presses
      for (let i = 0; i < 5; i++) {
        await page.keyboard.press('Tab');
        const newFocused = page.locator(':focus');
        if (await newFocused.count() > 0) {
          await expect(newFocused.first()).toBeVisible();
        }
      }
    });

    test('ARIA labels and semantic markup', async ({ page }) => {
      // Check for proper ARIA labels
      const elementsWithAriaLabel = page.locator('[aria-label]');
      const count = await elementsWithAriaLabel.count();
      
      if (count > 0) {
        for (let i = 0; i < Math.min(count, 5); i++) {
          const element = elementsWithAriaLabel.nth(i);
          const ariaLabel = await element.getAttribute('aria-label');
          expect(ariaLabel).toBeTruthy();
          expect(ariaLabel!.length).toBeGreaterThan(0);
        }
      }
      
      // Check for proper roles
      const elementsWithRole = page.locator('[role]');
      const roleCount = await elementsWithRole.count();
      expect(roleCount).toBeGreaterThanOrEqual(0);
    });

    test('color contrast and visual accessibility', async ({ page }) => {
      // This would require visual testing tools
      // For now, we'll check that text elements have proper contrast
      const textElements = page.locator('p, h1, h2, h3, h4, h5, h6, span, div');
      if (await textElements.count() > 0) {
        await expect(textElements.first()).toBeVisible();
      }
    });

    test('component loading performance', async ({ page }) => {
      const startTime = Date.now();
      
      await page.goto('/');
      await page.waitForLoadState('networkidle');
      
      const loadTime = Date.now() - startTime;
      
      // Assert reasonable load time (adjust threshold as needed)
      expect(loadTime).toBeLessThan(5000); // 5 seconds
    });

    test('responsive design across viewports', async ({ page }) => {
      const testViewports = [
        { width: 320, height: 568, name: 'Mobile' },
        { width: 768, height: 1024, name: 'Tablet' },
        { width: 1280, height: 720, name: 'Desktop' },
        { width: 1920, height: 1080, name: 'Large Desktop' }
      ];
      
      for (const viewport of testViewports) {
        await page.setViewportSize(viewport);
        await expect(page.locator('body')).toBeVisible();
        
        // Check that main content is still accessible
        // Skip script tags and look for actual content elements
        const mainContent = page.locator('main, [role="main"], .app-main, .app, h1, .card').first();
        await expect(mainContent).toBeVisible();
      }
    });
  });

  test.describe('Component Integration', () => {
    test('component composition - multiple components working together', async ({ page }) => {
      // Test that multiple components can coexist
      const interactiveElements = page.locator('button, input, select, textarea, a');
      const count = await interactiveElements.count();
      
      if (count > 0) {
        // Test first few elements
        for (let i = 0; i < Math.min(count, 3); i++) {
          const element = interactiveElements.nth(i);
          await expect(element).toBeVisible();
        }
      }
    });

    test('state management - component state persistence', async ({ page }) => {
      // Test form state persistence
      const inputs = page.locator('input[type="text"]');
      
      if (await inputs.count() > 0) {
        const input = inputs.first();
        await input.fill('Persistent test value');
        
        // Navigate away and back
        await page.goto('/');
        await page.waitForLoadState('networkidle');
        
        // Check if state is maintained (this depends on implementation)
        const newInput = page.locator('input[type="text"]').first();
        if (await newInput.count() > 0) {
          await expect(newInput).toBeVisible();
        }
      }
    });
  });
});
