#!/usr/bin/env bun
/**
 * ACCESSIBILITY TEST
 * ==================
 * Tests WCAG 2.1 AA compliance and accessibility features
 * - Buttons with discernible text (aria-labels)
 * - Form elements with labels
 * - CSS compatibility (backdrop-filter, user-select)
 * - HTTP headers (cache-control, security headers)
 * - Keyboard navigation
 * - Screen reader support
 */

import { chromium } from 'playwright';

const URL = "http://localhost:1999";

async function testAccessibility() {
  console.log('♿ ACCESSIBILITY TEST\n');
  console.log('='.repeat(70));

  const browser = await chromium.launch({ headless: false });
  const page = await browser.newPage({ viewport: { width: 1920, height: 1080 } });

  const errors = [];
  const testResults = [];

  page.on('console', msg => {
    if (msg.type() === 'error') {
      errors.push(msg.text());
      console.log(`❌ ERROR: ${msg.text()}`);
    }
  });

  console.log("\n1️⃣  Loading page...");
  const response = await page.goto(URL);
  await page.waitForTimeout(2000);

  // ========================================================================
  // TEST 1: HTTP Security Headers
  // ========================================================================
  console.log("\n2️⃣  Testing HTTP Security Headers...");
  const headers = response.headers();

  const securityHeaderTests = [
    { name: 'x-content-type-options', expected: 'nosniff' },
    { name: 'x-frame-options', expected: 'SAMEORIGIN' },
    { name: 'x-xss-protection', expected: '1; mode=block' },
    { name: 'referrer-policy', exists: true },
    { name: 'content-security-policy', exists: true },
  ];

  let securityPassed = 0;
  for (const test of securityHeaderTests) {
    const value = headers[test.name];
    if (test.expected) {
      const pass = value === test.expected;
      console.log(`   ${test.name}: ${pass ? '✅' : '❌'} (${value || 'missing'})`);
      if (pass) securityPassed++;
    } else if (test.exists) {
      const pass = !!value;
      console.log(`   ${test.name}: ${pass ? '✅' : '❌'} (${pass ? 'present' : 'missing'})`);
      if (pass) securityPassed++;
    }
  }

  const securityTestPassed = securityPassed === securityHeaderTests.length;
  console.log(`   ${securityTestPassed ? '✅ PASS' : '❌ FAIL'} - ${securityPassed}/${securityHeaderTests.length} security headers`);
  testResults.push({ test: 'Security Headers', passed: securityTestPassed });

  // ========================================================================
  // TEST 2: Cache-Control Headers
  // ========================================================================
  console.log("\n3️⃣  Testing Cache-Control Headers...");
  const cacheControl = headers['cache-control'];
  const hasCacheControl = !!cacheControl;
  console.log(`   cache-control: ${hasCacheControl ? '✅' : '❌'} (${cacheControl || 'missing'})`);
  console.log(`   ${hasCacheControl ? '✅ PASS' : '❌ FAIL'} - Cache-Control header present`);
  testResults.push({ test: 'Cache-Control Header', passed: hasCacheControl });

  // ========================================================================
  // TEST 3: Buttons with discernible text (aria-label)
  // ========================================================================
  console.log("\n4️⃣  Testing Buttons with Discernible Text...");

  const buttonA11y = await page.evaluate(() => {
    const buttons = document.querySelectorAll('button');
    const results = [];

    buttons.forEach(btn => {
      const hasAriaLabel = btn.hasAttribute('aria-label');
      const hasAriaLabelledBy = btn.hasAttribute('aria-labelledby');
      const hasTitle = btn.hasAttribute('title');
      const hasTextContent = btn.textContent.trim().length > 0;
      const hasVisibleText = Array.from(btn.querySelectorAll('span'))
        .some(span => span.textContent.trim().length > 0 && window.getComputedStyle(span).display !== 'none');

      const accessible = hasAriaLabel || hasAriaLabelledBy || hasTitle || hasTextContent || hasVisibleText;

      if (!accessible) {
        results.push({
          id: btn.id || 'no-id',
          class: btn.className,
          accessible: false
        });
      }
    });

    return {
      total: buttons.length,
      inaccessible: results,
      passed: results.length === 0
    };
  });

  console.log(`   Total buttons: ${buttonA11y.total}`);
  console.log(`   Inaccessible buttons: ${buttonA11y.inaccessible.length}`);
  if (buttonA11y.inaccessible.length > 0) {
    buttonA11y.inaccessible.forEach(btn => {
      console.log(`     ❌ Button: id="${btn.id}", class="${btn.class}"`);
    });
  }
  console.log(`   ${buttonA11y.passed ? '✅ PASS' : '❌ FAIL'} - All buttons have discernible text`);
  testResults.push({ test: 'Buttons Discernible Text', passed: buttonA11y.passed });

  // ========================================================================
  // TEST 4: Form elements with labels
  // ========================================================================
  console.log("\n5️⃣  Testing Form Elements with Labels...");

  const formA11y = await page.evaluate(() => {
    const inputs = document.querySelectorAll('input:not([type="hidden"]):not([type="submit"]):not([type="button"])');
    const results = [];

    inputs.forEach(input => {
      const hasId = input.id;
      const hasAriaLabel = input.hasAttribute('aria-label');
      const hasAriaLabelledBy = input.hasAttribute('aria-labelledby');
      const hasTitle = input.hasAttribute('title');
      const hasPlaceholder = input.hasAttribute('placeholder');

      // Check for associated label
      const hasAssociatedLabel = hasId ?
        document.querySelector(`label[for="${input.id}"]`) !== null : false;

      // Check if wrapped in a label
      const isWrappedInLabel = input.closest('label') !== null;

      const accessible = hasAriaLabel || hasAriaLabelledBy || hasTitle ||
                        hasAssociatedLabel || isWrappedInLabel || hasPlaceholder;

      if (!accessible) {
        results.push({
          id: input.id || 'no-id',
          type: input.type,
          name: input.name,
          accessible: false
        });
      }
    });

    return {
      total: inputs.length,
      inaccessible: results,
      passed: results.length === 0
    };
  });

  console.log(`   Total form inputs: ${formA11y.total}`);
  console.log(`   Inaccessible inputs: ${formA11y.inaccessible.length}`);
  if (formA11y.inaccessible.length > 0) {
    formA11y.inaccessible.forEach(input => {
      console.log(`     ❌ Input: id="${input.id}", type="${input.type}", name="${input.name}"`);
    });
  }
  console.log(`   ${formA11y.passed ? '✅ PASS' : '❌ FAIL'} - All form elements have labels`);
  testResults.push({ test: 'Form Elements Labels', passed: formA11y.passed });

  // ========================================================================
  // TEST 5: Toggle checkboxes accessibility
  // ========================================================================
  console.log("\n6️⃣  Testing Toggle Checkboxes Accessibility...");

  const toggleA11y = await page.evaluate(() => {
    const toggleIds = [
      'lengthToggle', 'iconToggle', 'themeToggle',
      'lengthToggleMenu', 'iconToggleMenu', 'themeToggleMenu'
    ];

    const results = [];

    toggleIds.forEach(id => {
      const toggle = document.getElementById(id);
      if (!toggle) return;

      const hasAriaLabel = toggle.hasAttribute('aria-label');
      const hasAriaLabelledBy = toggle.hasAttribute('aria-labelledby');
      const labelledById = toggle.getAttribute('aria-labelledby');
      const linkedLabel = labelledById ? document.getElementById(labelledById) : null;

      results.push({
        id,
        hasAriaLabel,
        hasAriaLabelledBy,
        linkedLabelExists: !!linkedLabel,
        accessible: hasAriaLabel || (hasAriaLabelledBy && !!linkedLabel)
      });
    });

    return {
      results,
      passed: results.every(r => r.accessible)
    };
  });

  toggleA11y.results.forEach(r => {
    const status = r.accessible ? '✅' : '❌';
    console.log(`   ${status} #${r.id}: aria-labelledby=${r.hasAriaLabelledBy}, linked-label=${r.linkedLabelExists}`);
  });
  console.log(`   ${toggleA11y.passed ? '✅ PASS' : '❌ FAIL'} - All toggle checkboxes accessible`);
  testResults.push({ test: 'Toggle Checkboxes Accessibility', passed: toggleA11y.passed });

  // ========================================================================
  // TEST 6: ARIA landmarks
  // ========================================================================
  console.log("\n7️⃣  Testing ARIA Landmarks...");

  const landmarks = await page.evaluate(() => {
    return {
      navigation: document.querySelectorAll('[role="navigation"], nav').length,
      main: document.querySelectorAll('[role="main"], main').length,
      dialog: document.querySelectorAll('[role="dialog"], dialog').length,
      region: document.querySelectorAll('[role="region"], section[aria-label]').length
    };
  });

  console.log(`   Navigation landmarks: ${landmarks.navigation}`);
  console.log(`   Main landmarks: ${landmarks.main}`);
  console.log(`   Dialog elements: ${landmarks.dialog}`);
  console.log(`   Regions: ${landmarks.region}`);

  const hasLandmarks = landmarks.navigation > 0;
  console.log(`   ${hasLandmarks ? '✅ PASS' : '⚠️  INFO'} - Has navigation landmarks`);
  testResults.push({ test: 'ARIA Landmarks', passed: hasLandmarks });

  // ========================================================================
  // TEST 7: Keyboard Navigation
  // ========================================================================
  console.log("\n8️⃣  Testing Keyboard Navigation...");

  // Test that interactive elements can receive focus
  const keyboardA11y = await page.evaluate(() => {
    const interactiveElements = document.querySelectorAll('button, a[href], input, select, textarea, [tabindex]:not([tabindex="-1"])');
    let focusableCount = 0;

    interactiveElements.forEach(el => {
      const style = window.getComputedStyle(el);
      if (style.display !== 'none' && style.visibility !== 'hidden') {
        focusableCount++;
      }
    });

    return {
      total: interactiveElements.length,
      focusable: focusableCount
    };
  });

  console.log(`   Total interactive elements: ${keyboardA11y.total}`);
  console.log(`   Focusable elements: ${keyboardA11y.focusable}`);
  console.log(`   ${keyboardA11y.focusable > 0 ? '✅ PASS' : '❌ FAIL'} - Has keyboard-accessible elements`);
  testResults.push({ test: 'Keyboard Navigation', passed: keyboardA11y.focusable > 0 });

  // ========================================================================
  // TEST 8: Modal Accessibility (dialog elements)
  // ========================================================================
  console.log("\n9️⃣  Testing Modal/Dialog Accessibility...");

  const modalA11y = await page.evaluate(() => {
    const dialogs = document.querySelectorAll('dialog');
    const results = [];

    dialogs.forEach(dialog => {
      const hasCloseButton = dialog.querySelector('[aria-label*="close" i], [aria-label*="cerrar" i], .info-modal-close') !== null;
      const hasAriaLabel = dialog.hasAttribute('aria-label') || dialog.hasAttribute('aria-labelledby');

      results.push({
        id: dialog.id || 'no-id',
        hasCloseButton,
        hasAriaLabel,
        accessible: hasCloseButton
      });
    });

    return {
      total: dialogs.length,
      results,
      passed: results.every(r => r.accessible)
    };
  });

  console.log(`   Total dialogs: ${modalA11y.total}`);
  modalA11y.results.forEach(r => {
    console.log(`   ${r.accessible ? '✅' : '❌'} #${r.id}: close-btn=${r.hasCloseButton}, aria-label=${r.hasAriaLabel}`);
  });
  console.log(`   ${modalA11y.passed ? '✅ PASS' : '❌ FAIL'} - All dialogs have close buttons`);
  testResults.push({ test: 'Modal Accessibility', passed: modalA11y.passed });

  // ========================================================================
  // TEST 9: Color Contrast (basic check via computed styles)
  // ========================================================================
  console.log("\n🔟 Testing Color Theme Support...");

  const themeSupport = await page.evaluate(() => {
    const html = document.documentElement;
    const body = document.body;

    // Check for theme switcher
    const themeSwitcher = document.getElementById('color-theme-switcher');

    // Check for CSS custom properties (variables)
    const styles = getComputedStyle(html);
    const hasColorVariables = styles.getPropertyValue('--color-text') ||
                             styles.getPropertyValue('--color-background') ||
                             styles.getPropertyValue('--text-color') ||
                             styles.getPropertyValue('--bg-color');

    return {
      hasThemeSwitcher: !!themeSwitcher,
      hasColorVariables: !!hasColorVariables,
      bodyClasses: body.className
    };
  });

  console.log(`   Theme switcher present: ${themeSupport.hasThemeSwitcher ? '✅' : '❌'}`);
  console.log(`   CSS color variables: ${themeSupport.hasColorVariables ? '✅' : '⚠️  Not detected'}`);
  console.log(`   Body classes: ${themeSupport.bodyClasses}`);
  console.log(`   ${themeSupport.hasThemeSwitcher ? '✅ PASS' : '⚠️  INFO'} - Theme switching available`);
  testResults.push({ test: 'Color Theme Support', passed: themeSupport.hasThemeSwitcher });

  // ========================================================================
  // TEST 10: Screen Reader Announcements
  // ========================================================================
  console.log("\n1️⃣1️⃣  Testing Screen Reader Announcements...");

  const srAnnouncements = await page.evaluate(() => {
    const liveRegions = document.querySelectorAll('[aria-live], [role="status"], [role="alert"]');
    const srOnlyElements = document.querySelectorAll('.sr-only, .visually-hidden');

    return {
      liveRegions: liveRegions.length,
      srOnlyElements: srOnlyElements.length
    };
  });

  console.log(`   Live regions (aria-live): ${srAnnouncements.liveRegions}`);
  console.log(`   Screen reader only elements: ${srAnnouncements.srOnlyElements}`);
  console.log(`   ${srAnnouncements.liveRegions > 0 ? '✅ PASS' : '⚠️  INFO'} - Has live regions for announcements`);
  testResults.push({ test: 'Screen Reader Announcements', passed: srAnnouncements.liveRegions > 0 });

  // ========================================================================
  // FINAL SUMMARY
  // ========================================================================
  console.log("\n" + "=".repeat(70));
  console.log("📊 ACCESSIBILITY TEST SUMMARY\n");

  const totalTests = testResults.length;
  const passedTests = testResults.filter(r => r.passed).length;
  const failedTests = totalTests - passedTests;

  testResults.forEach(result => {
    console.log(`   ${result.passed ? '✅' : '❌'} ${result.test}`);
  });

  console.log(`\n   Total: ${passedTests}/${totalTests} tests passed`);

  if (errors.length === 0) {
    console.log("\n✅ NO CONSOLE ERRORS");
  } else {
    console.log(`\n⚠️  ${errors.length} CONSOLE ERRORS`);
  }

  console.log("=".repeat(70) + "\n");

  if (failedTests === 0) {
    console.log("🎉 ALL ACCESSIBILITY TESTS PASSED!");
  } else {
    console.log("⚠️  SOME TESTS FAILED - See details above");
  }

  console.log("\nBrowser will stay open for manual inspection.");
  console.log("Press Ctrl+C when done.\n");

  await new Promise(() => {}); // Keep browser open
}

await testAccessibility();
