import { test, expect } from '@playwright/test';
import AxeBuilder from '@axe-core/playwright';

test.describe('Authentication Pages Accessibility', () => {
  test.describe('Login Page - /en/login', () => {
    test('should not have any WCAG 2.1 AA violations', async ({ page }) => {
      await page.goto('http://localhost:9000/en/login');

      const accessibilityScanResults = await new AxeBuilder({ page })
        .withTags(['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa'])
        .analyze();

      expect(accessibilityScanResults.violations).toEqual([]);
    });

    test('all form inputs have associated labels', async ({ page }) => {
      await page.goto('http://localhost:9000/en/login');

      const inputs = await page.locator('input:not([type="hidden"])').all();

      for (const input of inputs) {
        const id = await input.getAttribute('id');
        const ariaLabel = await input.getAttribute('aria-label');
        const ariaLabelledby = await input.getAttribute('aria-labelledby');
        const label = await page.locator(`label[for="${id}"]`).count();

        const hasLabel = ariaLabel || ariaLabelledby || label > 0;
        const inputName = await input.getAttribute('name') || await input.getAttribute('type');

        expect(hasLabel).toBeTruthy();
        console.log(`✓ Input "${inputName}" has label`);
      }
    });

    test('keyboard navigation works correctly', async ({ page }) => {
      await page.goto('http://localhost:9000/en/login');

      // Track tab order
      const tabOrder: string[] = [];

      // Tab through all interactive elements
      for (let i = 0; i < 10; i++) {
        await page.keyboard.press('Tab');
        const focused = await page.evaluate(() => {
          const el = document.activeElement;
          return {
            tag: el?.tagName,
            name: el?.getAttribute('name') || el?.getAttribute('aria-label') || el?.textContent?.trim().substring(0, 20),
            type: el?.getAttribute('type'),
          };
        });
        if (focused.name) {
          tabOrder.push(`${focused.tag}${focused.name ? `: ${focused.name}` : ''}`);
        }
      }

      console.log('Tab order:', tabOrder);
      expect(tabOrder.length).toBeGreaterThan(0);
    });

    test('form can be submitted with keyboard', async ({ page }) => {
      await page.goto('http://localhost:9000/en/login');

      // Tab to email field
      await page.keyboard.press('Tab');
      await page.keyboard.type('test@example.com');

      // Tab to password field
      await page.keyboard.press('Tab');
      await page.keyboard.type('TestPassword123!');

      // Tab to submit button
      await page.keyboard.press('Tab');

      // Press Enter to submit
      await page.keyboard.press('Enter');

      // Wait a moment for form submission
      await page.waitForTimeout(1000);

      // Form should have attempted submission (may show validation or redirect)
      const url = page.url();
      console.log('After submit URL:', url);

      // Should not still be on login page with no changes, or should show error
      const hasError = await page.locator('[role="alert"], [aria-live="polite"], .error, .text-red-500').count();
      const urlChanged = url !== 'http://localhost:9000/en/login';

      expect(hasError > 0 || urlChanged).toBeTruthy();
    });

    test('focus indicators are visible', async ({ page }) => {
      await page.goto('http://localhost:9000/en/login');

      const interactiveElements = await page.locator('input, button, a[href]').all();

      for (const element of interactiveElements) {
        await element.focus();

        const hasVisibleFocus = await element.evaluate((el) => {
          const style = window.getComputedStyle(el);
          const outlineWidth = style.outlineWidth;
          const outlineStyle = style.outlineStyle;
          const boxShadow = style.boxShadow;
          const border = style.borderWidth;

          // Has visible outline, box-shadow, or border
          return (
            (outlineWidth !== '0px' && outlineStyle !== 'none') ||
            boxShadow !== 'none' ||
            parseInt(border) > 0
          );
        });

        const elementInfo = await element.evaluate((el) => ({
          tag: el.tagName,
          type: el.getAttribute('type'),
          name: el.getAttribute('name') || el.getAttribute('aria-label'),
        }));

        expect(hasVisibleFocus).toBeTruthy();
        console.log(`✓ ${elementInfo.tag} has visible focus indicator`);
      }
    });

    test('error messages are accessible', async ({ page }) => {
      await page.goto('http://localhost:9000/en/login');

      // Submit empty form to trigger validation
      const submitButton = await page.locator('button[type="submit"]');
      await submitButton.click();

      await page.waitForTimeout(500);

      // Check if errors are present and accessible
      const invalidFields = await page.locator('[aria-invalid="true"]').all();

      if (invalidFields.length > 0) {
        for (const field of invalidFields) {
          const describedBy = await field.getAttribute('aria-describedby');
          const fieldName = await field.getAttribute('name');

          expect(describedBy).toBeTruthy();
          console.log(`✓ Field "${fieldName}" has aria-describedby: ${describedBy}`);

          if (describedBy) {
            const errorMessage = await page.locator(`#${describedBy}`).textContent();
            expect(errorMessage).toBeTruthy();
            expect(errorMessage!.length).toBeGreaterThan(0);
            console.log(`  Error message: "${errorMessage}"`);
          }
        }
      }
    });

    test('color contrast meets WCAG AA standards', async ({ page }) => {
      await page.goto('http://localhost:9000/en/login');

      const contrastResults = await new AxeBuilder({ page })
        .withTags(['wcag2aa'])
        .include(['color-contrast'])
        .analyze();

      const contrastViolations = contrastResults.violations.filter(
        (v) => v.id === 'color-contrast'
      );

      expect(contrastViolations).toEqual([]);
    });

    test('heading hierarchy is correct', async ({ page }) => {
      await page.goto('http://localhost:9000/en/login');

      const headings = await page.locator('h1, h2, h3, h4, h5, h6').all();
      const levels = await Promise.all(
        headings.map((h) => h.evaluate((el) => parseInt(el.tagName[1])))
      );

      console.log('Heading hierarchy:', levels);

      // Should have at least one h1
      const h1Count = levels.filter((l) => l === 1).length;
      expect(h1Count).toBeGreaterThanOrEqual(1);

      // No heading level skips
      for (let i = 1; i < levels.length; i++) {
        const diff = levels[i] - levels[i - 1];
        expect(diff).toBeLessThanOrEqual(1);
      }
    });

    test('has skip to main content link', async ({ page }) => {
      await page.goto('http://localhost:9000/en/login');

      // Press Tab to focus first element (should be skip link)
      await page.keyboard.press('Tab');

      const skipLink = await page.locator('a[href*="#main"], a[href*="#content"]').first();
      const skipLinkExists = await skipLink.count();

      if (skipLinkExists > 0) {
        console.log('✓ Skip link found');
        const skipLinkText = await skipLink.textContent();
        console.log(`  Text: "${skipLinkText}"`);
      } else {
        console.log('⚠ No skip link found');
      }
    });
  });

  test.describe('Signup Page - /en/signup', () => {
    test('should not have any WCAG 2.1 AA violations', async ({ page }) => {
      await page.goto('http://localhost:9000/en/signup');

      const accessibilityScanResults = await new AxeBuilder({ page })
        .withTags(['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa'])
        .analyze();

      expect(accessibilityScanResults.violations).toEqual([]);
    });

    test('all form inputs have associated labels', async ({ page }) => {
      await page.goto('http://localhost:9000/en/signup');

      const inputs = await page.locator('input:not([type="hidden"])').all();

      for (const input of inputs) {
        const id = await input.getAttribute('id');
        const ariaLabel = await input.getAttribute('aria-label');
        const ariaLabelledby = await input.getAttribute('aria-labelledby');
        const label = await page.locator(`label[for="${id}"]`).count();

        const hasLabel = ariaLabel || ariaLabelledby || label > 0;
        const inputName = await input.getAttribute('name') || await input.getAttribute('type');

        expect(hasLabel).toBeTruthy();
        console.log(`✓ Input "${inputName}" has label`);
      }
    });

    test('keyboard navigation works correctly', async ({ page }) => {
      await page.goto('http://localhost:9000/en/signup');

      // Track tab order
      const tabOrder: string[] = [];

      // Tab through all interactive elements
      for (let i = 0; i < 15; i++) {
        await page.keyboard.press('Tab');
        const focused = await page.evaluate(() => {
          const el = document.activeElement;
          return {
            tag: el?.tagName,
            name: el?.getAttribute('name') || el?.getAttribute('aria-label') || el?.textContent?.trim().substring(0, 20),
            type: el?.getAttribute('type'),
          };
        });
        if (focused.name) {
          tabOrder.push(`${focused.tag}${focused.name ? `: ${focused.name}` : ''}`);
        }
      }

      console.log('Tab order:', tabOrder);
      expect(tabOrder.length).toBeGreaterThan(0);
    });

    test('form can be navigated and submitted with keyboard', async ({ page }) => {
      await page.goto('http://localhost:9000/en/signup');

      // Tab through form fields
      await page.keyboard.press('Tab'); // First field
      await page.keyboard.type('Test User');

      await page.keyboard.press('Tab'); // Email
      await page.keyboard.type('test@example.com');

      await page.keyboard.press('Tab'); // Password
      await page.keyboard.type('TestPassword123!');

      await page.keyboard.press('Tab'); // Confirm password
      await page.keyboard.type('TestPassword123!');

      // Should be on submit button
      await page.keyboard.press('Tab');
      await page.keyboard.press('Enter');

      await page.waitForTimeout(1000);

      // Should have attempted submission
      const url = page.url();
      console.log('After submit URL:', url);

      const hasError = await page.locator('[role="alert"], [aria-live="polite"], .error').count();
      const urlChanged = url !== 'http://localhost:9000/en/signup';

      expect(hasError > 0 || urlChanged).toBeTruthy();
    });

    test('focus indicators are visible', async ({ page }) => {
      await page.goto('http://localhost:9000/en/signup');

      const interactiveElements = await page.locator('input, button, a[href]').all();

      let focusCount = 0;
      for (const element of interactiveElements) {
        await element.focus();

        const hasVisibleFocus = await element.evaluate((el) => {
          const style = window.getComputedStyle(el);
          const outlineWidth = style.outlineWidth;
          const outlineStyle = style.outlineStyle;
          const boxShadow = style.boxShadow;

          return (
            (outlineWidth !== '0px' && outlineStyle !== 'none') ||
            boxShadow !== 'none'
          );
        });

        if (hasVisibleFocus) focusCount++;
      }

      console.log(`✓ ${focusCount}/${interactiveElements.length} elements have visible focus`);
      expect(focusCount).toBeGreaterThan(0);
    });

    test('error messages are accessible', async ({ page }) => {
      await page.goto('http://localhost:9000/en/signup');

      // Submit empty form
      const submitButton = await page.locator('button[type="submit"]');
      await submitButton.click();

      await page.waitForTimeout(500);

      // Check for accessible error messages
      const invalidFields = await page.locator('[aria-invalid="true"]').all();

      if (invalidFields.length > 0) {
        for (const field of invalidFields) {
          const describedBy = await field.getAttribute('aria-describedby');
          const fieldName = await field.getAttribute('name');

          if (describedBy) {
            console.log(`✓ Field "${fieldName}" has aria-describedby: ${describedBy}`);
            const errorMessage = await page.locator(`#${describedBy}`).textContent();
            expect(errorMessage).toBeTruthy();
            console.log(`  Error message: "${errorMessage}"`);
          } else {
            console.log(`⚠ Field "${fieldName}" missing aria-describedby`);
          }
        }
      }
    });

    test('required fields are marked', async ({ page }) => {
      await page.goto('http://localhost:9000/en/signup');

      const requiredFields = await page.locator('input[required], input[aria-required="true"]').all();

      console.log(`Found ${requiredFields.length} required fields`);
      expect(requiredFields.length).toBeGreaterThan(0);

      for (const field of requiredFields) {
        const name = await field.getAttribute('name');
        const ariaRequired = await field.getAttribute('aria-required');
        const required = await field.getAttribute('required');

        console.log(`✓ Field "${name}" is required (aria-required: ${ariaRequired})`);
        expect(required !== null || ariaRequired === 'true').toBeTruthy();
      }
    });

    test('heading hierarchy is correct', async ({ page }) => {
      await page.goto('http://localhost:9000/en/signup');

      const headings = await page.locator('h1, h2, h3, h4, h5, h6').all();
      const levels = await Promise.all(
        headings.map((h) => h.evaluate((el) => parseInt(el.tagName[1])))
      );

      console.log('Heading hierarchy:', levels);

      // Should have at least one h1
      const h1Count = levels.filter((l) => l === 1).length;
      expect(h1Count).toBeGreaterThanOrEqual(1);
    });
  });

  test.describe('Comparative Tests', () => {
    test('both pages have consistent accessibility patterns', async ({ page }) => {
      const pages = [
        'http://localhost:9000/en/login',
        'http://localhost:9000/en/signup'
      ];

      const results = [];

      for (const url of pages) {
        await page.goto(url);

        const scanResults = await new AxeBuilder({ page })
          .withTags(['wcag2aa'])
          .analyze();

        results.push({
          url,
          violations: scanResults.violations.length,
          passes: scanResults.passes.length,
          incomplete: scanResults.incomplete.length,
        });
      }

      console.log('Accessibility comparison:', JSON.stringify(results, null, 2));

      // Both pages should have zero violations
      results.forEach((result) => {
        expect(result.violations).toBe(0);
      });
    });
  });
});
