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

/**
 * WCAG 2.1 Level AA Comprehensive Accessibility Audit
 *
 * Tests all critical pages for:
 * - WCAG 2.1 Level AA compliance
 * - Keyboard navigation
 * - Screen reader compatibility
 * - Color contrast
 * - Form accessibility
 * - ARIA implementation
 */

test.describe('WCAG 2.1 AA Compliance Audit', () => {

  // ==========================================
  // 1. HOMEPAGE ACCESSIBILITY
  // ==========================================

  test.describe('Homepage (English)', () => {
    test('should have no WCAG AA violations', async ({ page }) => {
      await page.goto('http://localhost:9000/en');

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

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

    test('should have proper landmarks and semantic structure', async ({ page }) => {
      await page.goto('http://localhost:9000/en');

      // Check for required landmarks
      const header = await page.locator('header').count();
      const nav = await page.locator('nav').count();
      const main = await page.locator('main').count();
      const footer = await page.locator('footer').count();

      expect(header).toBeGreaterThanOrEqual(1);
      expect(nav).toBeGreaterThanOrEqual(1);
      expect(main).toBe(1);
      expect(footer).toBeGreaterThanOrEqual(1);
    });

    test('should have proper heading hierarchy', async ({ page }) => {
      await page.goto('http://localhost:9000/en');

      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])))
      );

      // Should have exactly one h1
      const h1Count = levels.filter(l => l === 1).length;
      expect(h1Count).toBe(1);

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

    test('should be keyboard navigable', async ({ page }) => {
      await page.goto('http://localhost:9000/en');

      // Tab through interactive elements
      const interactiveElements = [];
      for (let i = 0; i < 10; i++) {
        await page.keyboard.press('Tab');
        const focused = await page.evaluate(() => {
          const el = document.activeElement;
          return el ? el.tagName + (el.getAttribute('aria-label') ? `[${el.getAttribute('aria-label')}]` : '') : null;
        });
        if (focused) interactiveElements.push(focused);
      }

      // Should have tabbed through at least 5 elements
      expect(interactiveElements.length).toBeGreaterThanOrEqual(5);
    });
  });

  test.describe('Homepage (Arabic - RTL)', () => {
    test('should have no WCAG AA violations in RTL', async ({ page }) => {
      await page.goto('http://localhost:9000/ar');

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

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

    test('should have correct RTL attributes', async ({ page }) => {
      await page.goto('http://localhost:9000/ar');

      const html = page.locator('html');
      expect(await html.getAttribute('dir')).toBe('rtl');
      expect(await html.getAttribute('lang')).toBe('ar');
    });
  });

  // ==========================================
  // 2. DEMO BOOKING SCHEDULER
  // ==========================================

  test.describe('Demo Booking Scheduler', () => {
    test('should have no WCAG AA violations', async ({ page }) => {
      await page.goto('http://localhost:9000/en/demo');

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

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

    test('form fields should have proper labels', async ({ page }) => {
      await page.goto('http://localhost:9000/en/demo');

      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();

        // Every input should have either aria-label, aria-labelledby, or associated <label>
        const hasLabel = ariaLabel || ariaLabelledBy || label > 0;
        expect(hasLabel).toBeTruthy();
      }
    });

    test('should be keyboard navigable', async ({ page }) => {
      await page.goto('http://localhost:9000/en/demo');

      // Tab through form
      await page.keyboard.press('Tab'); // First field
      const firstFocused = await page.evaluate(() => document.activeElement?.getAttribute('name'));
      expect(firstFocused).toBeTruthy();

      // Should be able to navigate entire form
      for (let i = 0; i < 15; i++) {
        await page.keyboard.press('Tab');
      }

      // Should not be trapped
      const lastFocused = await page.evaluate(() => document.activeElement?.tagName);
      expect(lastFocused).toBeTruthy();
    });

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

      // Try to submit empty form
      const submitButton = await page.locator('button[type="submit"]');
      if (await submitButton.count() > 0) {
        await submitButton.click();
        await page.waitForTimeout(1000);

        // Check if error messages are linked to fields
        const invalidInputs = await page.locator('[aria-invalid="true"]').all();

        for (const input of invalidInputs) {
          const describedBy = await input.getAttribute('aria-describedby');
          if (describedBy) {
            const errorMsg = await page.locator(`#${describedBy}`).textContent();
            expect(errorMsg).toBeTruthy();
            expect(errorMsg!.length).toBeGreaterThan(0);
          }
        }
      }
    });
  });

  // ==========================================
  // 3. SIGNUP FLOW ACCESSIBILITY
  // ==========================================

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

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

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

    test('signup form fields should be properly labeled', 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 name = await input.getAttribute('name');
        const ariaLabel = await input.getAttribute('aria-label');
        const label = await page.locator(`label[for="${id}"]`).count();

        const hasLabel = ariaLabel || label > 0;
        expect(hasLabel).toBeTruthy();
      }
    });

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

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

      // Should have at least email, password, name
      expect(requiredFields.length).toBeGreaterThanOrEqual(3);

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

        expect(required !== null || ariaRequired === 'true').toBeTruthy();
      }
    });

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

      // Tab through all fields
      const tabOrder = [];
      for (let i = 0; i < 6; i++) {
        await page.keyboard.press('Tab');
        const focused = await page.evaluate(() => document.activeElement?.getAttribute('name'));
        if (focused) tabOrder.push(focused);
      }

      // Should have logical tab order
      expect(tabOrder.length).toBeGreaterThanOrEqual(3);
    });
  });

  // ==========================================
  // 4. LOGIN PAGE ACCESSIBILITY
  // ==========================================

  test.describe('Login Page', () => {
    test('should have no WCAG AA violations', async ({ page }) => {
      await page.goto('http://localhost:9000/en/login');

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

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

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

      // Check form fields have labels
      const emailField = await page.locator('[name="email"], [type="email"]');
      const passwordField = await page.locator('[name="password"], [type="password"]');

      if (await emailField.count() > 0) {
        const emailId = await emailField.first().getAttribute('id');
        const emailLabel = await page.locator(`label[for="${emailId}"]`).count();
        const emailAriaLabel = await emailField.first().getAttribute('aria-label');

        expect(emailLabel > 0 || emailAriaLabel).toBeTruthy();
      }

      if (await passwordField.count() > 0) {
        const passwordId = await passwordField.first().getAttribute('id');
        const passwordLabel = await page.locator(`label[for="${passwordId}"]`).count();
        const passwordAriaLabel = await passwordField.first().getAttribute('aria-label');

        expect(passwordLabel > 0 || passwordAriaLabel).toBeTruthy();
      }
    });
  });

  // ==========================================
  // 5. PRICING PAGE ACCESSIBILITY
  // ==========================================

  test.describe('Pricing Page', () => {
    test('should have no WCAG AA violations', async ({ page }) => {
      await page.goto('http://localhost:9000/en/pricing');

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

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

    test('pricing cards should be accessible', async ({ page }) => {
      await page.goto('http://localhost:9000/en/pricing');

      // Check if pricing cards have proper structure
      const articles = await page.locator('article, [role="article"]').count();
      const sections = await page.locator('section').count();

      expect(articles + sections).toBeGreaterThan(0);
    });

    test('CTA buttons should be accessible', async ({ page }) => {
      await page.goto('http://localhost:9000/en/pricing');

      const buttons = await page.locator('button, a[role="button"]').all();

      for (const button of buttons) {
        const text = await button.textContent();
        const ariaLabel = await button.getAttribute('aria-label');

        // Button should have text or aria-label
        expect(text || ariaLabel).toBeTruthy();
      }
    });
  });

  // ==========================================
  // 6. BLOG LISTING ACCESSIBILITY
  // ==========================================

  test.describe('Blog Listing', () => {
    test('should have no WCAG AA violations', async ({ page }) => {
      await page.goto('http://localhost:9000/en/blog');

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

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

    test('blog posts should be in articles or proper semantic structure', async ({ page }) => {
      await page.goto('http://localhost:9000/en/blog');

      const articles = await page.locator('article').count();
      expect(articles).toBeGreaterThan(0);
    });
  });

  // ==========================================
  // 7. CONTACT FORM ACCESSIBILITY
  // ==========================================

  test.describe('Contact Form', () => {
    test('should have no WCAG AA violations', async ({ page }) => {
      await page.goto('http://localhost:9000/en/contact');

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

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

    test('contact form fields should be labeled', async ({ page }) => {
      await page.goto('http://localhost:9000/en/contact');

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

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

        expect(ariaLabel || label > 0).toBeTruthy();
      }
    });
  });

  // ==========================================
  // 8. INDUSTRY PAGES SAMPLE
  // ==========================================

  test.describe('Industry Pages Sample', () => {
    const industryPages = [
      '/en/industries/healthcare',
      '/en/industries/beauty-wellness',
      '/en/industries/hotels-accommodation'
    ];

    for (const industryPage of industryPages) {
      test(`${industryPage} should have no WCAG AA violations`, async ({ page }) => {
        await page.goto(`http://localhost:9000${industryPage}`);

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

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

  // ==========================================
  // 9. IMAGE ACCESSIBILITY
  // ==========================================

  test.describe('Image Accessibility', () => {
    test('all images should have alt text', async ({ page }) => {
      await page.goto('http://localhost:9000/en');

      const images = await page.locator('img').all();

      for (const img of images) {
        const alt = await img.getAttribute('alt');
        // Alt attribute must exist (can be empty for decorative)
        expect(alt).not.toBeNull();
      }
    });
  });

  // ==========================================
  // 10. FOCUS MANAGEMENT
  // ==========================================

  test.describe('Focus Management', () => {
    test('interactive elements should have visible focus', async ({ page }) => {
      await page.goto('http://localhost:9000/en');

      const firstButton = await page.locator('button, a').first();
      await firstButton.focus();

      const outlineWidth = await firstButton.evaluate(el => {
        const style = window.getComputedStyle(el);
        return style.outlineWidth;
      });

      // Should have some visible focus indicator
      expect(outlineWidth).toBeTruthy();
    });

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

      // Tab once to potentially reveal skip link
      await page.keyboard.press('Tab');

      // Check for skip link (may be visually hidden)
      const skipLink = await page.locator('a[href="#main-content"], a[href="#main"], a:has-text("Skip to")').count();

      // This is informational - not all sites have skip links
      console.log(`Skip link present: ${skipLink > 0}`);
    });
  });

  // ==========================================
  // 11. COLOR CONTRAST CHECKS
  // ==========================================

  test.describe('Color Contrast', () => {
    test('should have sufficient color contrast', async ({ page }) => {
      await page.goto('http://localhost:9000/en');

      const contrastResults = await new AxeBuilder({ page })
        .withTags(['wcag2aa'])
        .disableRules(['duplicate-id', 'landmark-unique']) // Focus on contrast
        .analyze();

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

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

  // ==========================================
  // 12. FORM VALIDATION ACCESSIBILITY
  // ==========================================

  test.describe('Form Validation Accessibility', () => {
    test('error messages should be associated with fields', async ({ page }) => {
      await page.goto('http://localhost:9000/en/signup');

      // Submit empty form to trigger validation
      const submitButton = await page.locator('button[type="submit"]');
      if (await submitButton.count() > 0) {
        await submitButton.click();
        await page.waitForTimeout(1000);

        // Check invalid fields have proper ARIA
        const invalidFields = await page.locator('[aria-invalid="true"]').all();

        for (const field of invalidFields) {
          const describedBy = await field.getAttribute('aria-describedby');

          if (describedBy) {
            // Error message should exist
            const errorMessage = await page.locator(`#${describedBy}`).textContent();
            expect(errorMessage).toBeTruthy();
            expect(errorMessage!.length).toBeGreaterThan(0);
          }
        }
      }
    });
  });
});
