/**
 * Mobile UI Audit - Comprehensive Issue Detection
 *
 * This test file detects mobile UI issues with strict pass/fail thresholds.
 * Tests will fail CI when critical issues are found.
 *
 * Thresholds:
 * - Overflowing elements: 0 (zero tolerance - breaks layout)
 * - Missing labels: 0 (accessibility requirement)
 * - Small touch targets: < 4 (allow 3 edge cases per page)
 * - Overlapping elements: < 2 (usability issue)
 */

import { test, expect } from '@playwright/test';
const { MIN_TOUCH_TARGET, PAGES } = require('./helpers/mobile-utils');

// ============================================
// DETAILED AUDIT TESTS - Report Issues
// ============================================

test.describe('Mobile UI Audit - Issue Detection', () => {
  for (const pageInfo of PAGES) {
    test(`${pageInfo.name} - Full UI Audit`, async ({ page, isMobile }) => {
      if (!isMobile) {
        test.skip();
        return;
      }

      await page.goto(pageInfo.path);
      await page.waitForLoadState('domcontentloaded');

      // Wait for dynamic content
      if (pageInfo.path === '/settings/') {
        await page.waitForSelector('.ldr-loading-spinner', { state: 'hidden', timeout: 10000 }).catch(() => {});
        // Wait for settings form to be rendered
        await page.waitForSelector('.ldr-settings-form, #settings-form, .ldr-settings-item', { timeout: 10000 }).catch(() => {});
        await page.locator('.ldr-settings-item, input[id], select[id]').first().waitFor({ state: 'visible', timeout: 10000 }).catch(() => {});
      }

      const auditResults = await page.evaluate((MIN_SIZE) => {
        const results = {
          page: window.location.pathname,
          viewport: { width: window.innerWidth, height: window.innerHeight },
          issues: {
            smallTouchTargets: [],
            smallText: [],
            overflowingElements: [],
            overlappingElements: [],
            contrastIssues: [],
            missingLabels: [],
          },
          stats: {
            totalButtons: 0,
            totalInputs: 0,
            totalLinks: 0,
          },
        };

        // 1. Check for small touch targets
        const interactiveElements = document.querySelectorAll(
          'button, a, input:not([type="hidden"]), select, textarea, [role="button"], .btn'
        );

        interactiveElements.forEach((el) => {
          const rect = el.getBoundingClientRect();
          const style = window.getComputedStyle(el);

          if (style.display === 'none' || style.visibility === 'hidden') return;
          if (rect.width === 0 || rect.height === 0) return;

          // Count elements
          if (el.tagName === 'BUTTON' || el.classList.contains('btn')) results.stats.totalButtons++;
          if (el.tagName === 'INPUT' || el.tagName === 'SELECT' || el.tagName === 'TEXTAREA')
            results.stats.totalInputs++;
          if (el.tagName === 'A') results.stats.totalLinks++;

          // Checkboxes and radio buttons are allowed to be smaller (24x24px meets WCAG 2.5.8)
          // because they have associated clickable labels that provide the full touch target
          const inputType = el.getAttribute('type');
          if (inputType === 'checkbox' || inputType === 'radio') {
            // Still report very small ones (below WCAG minimum 24px)
            if (rect.width < 24 || rect.height < 24) {
              results.issues.smallTouchTargets.push({
                tag: el.tagName.toLowerCase(),
                type: inputType,
                class: el.className?.toString().slice(0, 50) || '',
                text: (el.textContent || el.getAttribute('placeholder') || '').trim().slice(0, 30),
                size: `${Math.round(rect.width)}x${Math.round(rect.height)}`,
                location: `${Math.round(rect.x)},${Math.round(rect.y)}`,
              });
            }
            return; // Skip full 44px check for checkboxes/radios
          }

          // Check size
          if (rect.width < MIN_SIZE || rect.height < MIN_SIZE) {
            results.issues.smallTouchTargets.push({
              tag: el.tagName.toLowerCase(),
              type: inputType || '',
              class: el.className?.toString().slice(0, 50) || '',
              text: (el.textContent || el.getAttribute('placeholder') || '').trim().slice(0, 30),
              size: `${Math.round(rect.width)}x${Math.round(rect.height)}`,
              location: `${Math.round(rect.x)},${Math.round(rect.y)}`,
            });
          }
        });

        // 2. Check for small text
        const textElements = document.querySelectorAll('p, span, div, li, a, label, h1, h2, h3, h4, h5, h6, td, th');
        textElements.forEach((el) => {
          const style = window.getComputedStyle(el);
          const fontSize = parseFloat(style.fontSize);

          if (style.display === 'none' || style.visibility === 'hidden') return;
          if (!el.textContent.trim()) return;

          if (fontSize < 12) {
            const rect = el.getBoundingClientRect();
            // Only report if visible in viewport
            if (rect.top >= 0 && rect.top < window.innerHeight) {
              results.issues.smallText.push({
                tag: el.tagName.toLowerCase(),
                text: el.textContent.trim().slice(0, 40),
                fontSize: Math.round(fontSize * 10) / 10,
                location: `${Math.round(rect.x)},${Math.round(rect.y)}`,
              });
            }
          }
        });

        // Limit small text to first 10
        results.issues.smallText = results.issues.smallText.slice(0, 10);

        // 3. Check for overflowing elements
        // Helper function to check if element is inside a scrollable container
        const isInScrollableContainer = (el) => {
          let parent = el.parentElement;
          while (parent) {
            const style = window.getComputedStyle(parent);
            const overflowX = style.overflowX;
            // Check if parent has horizontal scroll enabled
            if (overflowX === 'auto' || overflowX === 'scroll') {
              return true;
            }
            // Also check for common scrollable container classes
            if (parent.classList.contains('ldr-settings-tabs') ||
                parent.classList.contains('nav-tabs') ||
                parent.classList.contains('ldr-tab-navigation') ||
                parent.getAttribute('role') === 'tablist') {
              return true;
            }
            parent = parent.parentElement;
          }
          return false;
        };

        document.querySelectorAll('*').forEach((el) => {
          const rect = el.getBoundingClientRect();
          if (rect.right > window.innerWidth + 5) {
            // Allow 5px tolerance
            // Skip elements inside scrollable containers - this is expected behavior
            if (isInScrollableContainer(el)) {
              return;
            }
            // Skip invisible elements — they have bounding rects in WebKit
            // but don't cause visible overflow
            const style = window.getComputedStyle(el);
            if (style.display === 'none' || style.visibility === 'hidden' || style.opacity === '0') {
              return;
            }
            // Skip zero-area elements (e.g. collapsed containers)
            if (rect.width === 0 || rect.height === 0) {
              return;
            }
            results.issues.overflowingElements.push({
              tag: el.tagName.toLowerCase(),
              class: el.className?.toString().slice(0, 50) || '',
              overflow: Math.round(rect.right - window.innerWidth),
            });
          }
        });

        // Limit overflowing to first 5
        results.issues.overflowingElements = results.issues.overflowingElements.slice(0, 5);

        // 4. Check for inputs missing labels
        document.querySelectorAll('input:not([type="hidden"]), select, textarea').forEach((input) => {
          const id = input.id;
          const hasLabel = id && document.querySelector(`label[for="${id}"]`);
          const hasAriaLabel = input.getAttribute('aria-label');
          const hasPlaceholder = input.getAttribute('placeholder');
          const parentLabel = input.closest('label');

          if (!hasLabel && !hasAriaLabel && !parentLabel && !hasPlaceholder) {
            results.issues.missingLabels.push({
              tag: input.tagName.toLowerCase(),
              type: input.getAttribute('type') || '',
              name: input.getAttribute('name') || '',
            });
          }
        });

        // Limit missing labels to first 5
        results.issues.missingLabels = results.issues.missingLabels.slice(0, 5);

        return results;
      }, MIN_TOUCH_TARGET);

      // Log the audit results
      console.log(`\n========== ${pageInfo.name} UI AUDIT ==========`);
      console.log(`Viewport: ${auditResults.viewport.width}x${auditResults.viewport.height}`);
      console.log(
        `Stats: ${auditResults.stats.totalButtons} buttons, ${auditResults.stats.totalInputs} inputs, ${auditResults.stats.totalLinks} links`
      );

      // === SMALL TOUCH TARGETS ===
      if (auditResults.issues.smallTouchTargets.length > 0) {
        console.log(`\n⚠️ Small Touch Targets (${auditResults.issues.smallTouchTargets.length}):`);
        auditResults.issues.smallTouchTargets.forEach((item) => {
          console.log(`  - ${item.tag}[${item.type}]: ${item.size} "${item.text}"`);
        });
      }

      expect(
        auditResults.issues.smallTouchTargets.length,
        `${pageInfo.name} should have at most 3 small touch targets (found ${auditResults.issues.smallTouchTargets.length}): ` +
        auditResults.issues.smallTouchTargets.slice(0, 5).map(t => `${t.tag}[${t.type}] ${t.size}`).join(', ')
      ).toBeLessThan(4);

      // === SMALL TEXT (diagnostic only - context dependent) ===
      if (auditResults.issues.smallText.length > 0) {
        console.log(`\n⚠️ Small Text (${auditResults.issues.smallText.length}):`);
        auditResults.issues.smallText.forEach((item) => {
          console.log(`  - ${item.tag}: ${item.fontSize}px "${item.text}"`);
        });
      }

      // === OVERFLOWING ELEMENTS (critical - zero tolerance) ===
      if (auditResults.issues.overflowingElements.length > 0) {
        console.log(`\n❌ Overflowing Elements (${auditResults.issues.overflowingElements.length}):`);
        auditResults.issues.overflowingElements.forEach((item) => {
          console.log(`  - ${item.tag}.${item.class}: ${item.overflow}px overflow`);
        });
      }

      expect(
        auditResults.issues.overflowingElements.length,
        `${pageInfo.name} should have no horizontally overflowing elements`
      ).toBe(0);

      // === MISSING LABELS (accessibility - some tolerance for dynamic content) ===
      if (auditResults.issues.missingLabels.length > 0) {
        console.log(`\n⚠️ Inputs Missing Labels (${auditResults.issues.missingLabels.length}):`);
        auditResults.issues.missingLabels.forEach((item) => {
          console.log(`  - ${item.tag}[${item.type}] name="${item.name}"`);
        });
      }

      // Settings page has complex dynamic forms with some edge cases
      // Allow up to 2 missing labels for forms with many dynamically generated inputs
      const maxMissingLabels = pageInfo.path === '/settings/' ? 2 : 0;
      expect(
        auditResults.issues.missingLabels.length,
        `${pageInfo.name} inputs should have accessible labels (max ${maxMissingLabels} allowed)`
      ).toBeLessThanOrEqual(maxMissingLabels);

      console.log('\n' + '='.repeat(50));

      // Take a screenshot for visual reference
      await page.screenshot({
        path: `test-results/audit-${pageInfo.name.toLowerCase().replace(/\s+/g, '-')}.png`,
        fullPage: false,
      });
    });
  }
});

// ============================================
// SPECIFIC ELEMENT TESTS
// ============================================

test.describe('Mobile UI Audit - Specific Elements', () => {
  test('Research page - Form layout audit', async ({ page, isMobile }) => {
    if (!isMobile) {
      test.skip();
      return;
    }

    await page.goto('/');
    await page.waitForLoadState('domcontentloaded');

    const formElements = await page.evaluate(() => {
      const elements = [];

      // Query textarea
      const textarea = document.querySelector('#query, textarea');
      if (textarea) {
        const rect = textarea.getBoundingClientRect();
        const style = window.getComputedStyle(textarea);
        elements.push({
          name: 'Query Textarea',
          size: `${Math.round(rect.width)}x${Math.round(rect.height)}`,
          fontSize: parseFloat(style.fontSize),
          placeholder: textarea.getAttribute('placeholder'),
        });
      }

      // Mode selection
      const modeSelection = document.querySelector('.ldr-mode-selection');
      if (modeSelection) {
        const rect = modeSelection.getBoundingClientRect();
        elements.push({
          name: 'Mode Selection',
          size: `${Math.round(rect.width)}x${Math.round(rect.height)}`,
        });
      }

      // Start button
      const startBtn = document.querySelector('#start-research-btn, button[type="submit"]');
      if (startBtn) {
        const rect = startBtn.getBoundingClientRect();
        elements.push({
          name: 'Start Research Button',
          size: `${Math.round(rect.width)}x${Math.round(rect.height)}`,
          text: startBtn.textContent.trim(),
        });
      }

      // Advanced options toggle
      const advToggle = document.querySelector('.ldr-advanced-options-toggle');
      if (advToggle) {
        const rect = advToggle.getBoundingClientRect();
        elements.push({
          name: 'Advanced Options Toggle',
          size: `${Math.round(rect.width)}x${Math.round(rect.height)}`,
        });
      }

      return elements;
    });

    console.log('\n========== Research Page Form Layout ==========');
    formElements.forEach((el) => {
      console.log(`${el.name}: ${el.size}${el.fontSize ? ` (${el.fontSize}px font)` : ''}`);
    });
    console.log('='.repeat(50));

    // Assert on critical form elements
    const textarea = formElements.find(e => e.name === 'Query Textarea');
    if (textarea) {
      const [_width, height] = textarea.size.split('x').map(Number);
      expect(height, 'Query textarea should be at least 80px tall').toBeGreaterThanOrEqual(80);
      expect(textarea.fontSize, 'Query textarea font >= 16px (prevents iOS zoom)').toBeGreaterThanOrEqual(16);
    }

    const startBtn = formElements.find(e => e.name === 'Start Research Button');
    if (startBtn) {
      const [_width, height] = startBtn.size.split('x').map(Number);
      expect(height, 'Start button meets touch target minimum').toBeGreaterThanOrEqual(44);
    }
  });

  test('Settings page - Settings cards audit', async ({ page, isMobile }) => {
    if (!isMobile) {
      test.skip();
      return;
    }

    await page.goto('/settings/');
    await page.waitForLoadState('domcontentloaded');
    await page.waitForSelector('.ldr-loading-spinner', { state: 'hidden', timeout: 10000 }).catch(() => {});

    // Wait for settings tabs or settings items to be rendered
    await page.waitForSelector('[data-tab], .ldr-settings-tab, .ldr-settings-item, input[id], select[id]', { timeout: 15000 }).catch(() => {});
    await page.locator('.ldr-settings-item, input[id], select[id]').first().waitFor({ state: 'visible', timeout: 10000 }).catch(() => {});

    const settingsInfo = await page.evaluate(() => {
      const info = {
        totalSettings: 0,
        settingTypes: {},
        sampleSettings: [],
      };

      // Check for settings items with various possible selectors
      const settingItems = document.querySelectorAll(
        '.ldr-settings-item, [class*="setting-item"], [data-key], .form-group'
      );
      info.totalSettings = settingItems.length;

      settingItems.forEach((item, i) => {
        const input = item.querySelector('input, select, textarea');
        if (input) {
          const type = input.type || input.tagName.toLowerCase();
          info.settingTypes[type] = (info.settingTypes[type] || 0) + 1;

          if (i < 5) {
            const rect = input.getBoundingClientRect();
            const label = item.querySelector('label, .ldr-setting-label');
            info.sampleSettings.push({
              type,
              size: `${Math.round(rect.width)}x${Math.round(rect.height)}`,
              label: label?.textContent.trim().slice(0, 30) || 'No label',
            });
          }
        }
      });

      return info;
    });

    console.log('\n========== Settings Page Audit ==========');
    console.log(`Total settings: ${settingsInfo.totalSettings}`);
    console.log('Setting types:', settingsInfo.settingTypes);
    console.log('\nSample settings:');
    settingsInfo.sampleSettings.forEach((s) => {
      console.log(`  - ${s.type}: ${s.size} "${s.label}"`);
    });
    console.log('='.repeat(50));

    // Settings should load successfully
    expect(settingsInfo.totalSettings, 'Settings page should have settings loaded').toBeGreaterThan(0);
  });

  test('News page - News templates audit', async ({ page, isMobile }) => {
    if (!isMobile) {
      test.skip();
      return;
    }

    await page.goto('/news/');
    await page.waitForLoadState('domcontentloaded');

    const newsInfo = await page.evaluate(() => {
      const info = {
        templates: [],
        actionButtons: [],
      };

      // News templates
      const templates = document.querySelectorAll('[class*="template"], .news-template');
      templates.forEach((t) => {
        const rect = t.getBoundingClientRect();
        info.templates.push({
          text: t.textContent.trim().slice(0, 30),
          size: `${Math.round(rect.width)}x${Math.round(rect.height)}`,
        });
      });

      // Action buttons
      const buttons = document.querySelectorAll('button');
      buttons.forEach((b) => {
        const rect = b.getBoundingClientRect();
        if (rect.height > 0) {
          info.actionButtons.push({
            text: b.textContent.trim().slice(0, 20),
            size: `${Math.round(rect.width)}x${Math.round(rect.height)}`,
          });
        }
      });

      return info;
    });

    console.log('\n========== News Page Audit ==========');
    console.log(`Templates (${newsInfo.templates.length}):`);
    newsInfo.templates.slice(0, 5).forEach((t) => {
      console.log(`  - ${t.size}: "${t.text}"`);
    });
    console.log(`\nAction Buttons (${newsInfo.actionButtons.length}):`);
    newsInfo.actionButtons.slice(0, 10).forEach((b) => {
      console.log(`  - ${b.size}: "${b.text}"`);
    });
    console.log('='.repeat(50));

    // Check that action buttons meet touch target requirements
    const smallButtons = newsInfo.actionButtons.filter(b => {
      const [_width, height] = b.size.split('x').map(Number);
      return height < 44;
    });

    expect(
      smallButtons.length,
      `News page action buttons should meet 44px touch target`
    ).toBe(0);
  });

  test('Metrics page - Dashboard cards audit', async ({ page, isMobile }) => {
    if (!isMobile) {
      test.skip();
      return;
    }

    await page.goto('/metrics/');
    await page.waitForLoadState('domcontentloaded');

    const metricsInfo = await page.evaluate(() => {
      const info = {
        pageHeight: document.body.scrollHeight,
        viewportHeight: window.innerHeight,
        cards: [],
        sections: [],
      };

      // Metric cards
      const cards = document.querySelectorAll(
        '.ldr-metric-card, .metric-card, [class*="metric"], .ldr-card'
      );
      cards.forEach((c, i) => {
        if (i < 10) {
          const rect = c.getBoundingClientRect();
          info.cards.push({
            class: c.className?.toString().slice(0, 40),
            size: `${Math.round(rect.width)}x${Math.round(rect.height)}`,
          });
        }
      });

      // Sections
      const sections = document.querySelectorAll('h2, h3, .section-title');
      sections.forEach((s) => {
        info.sections.push(s.textContent.trim().slice(0, 30));
      });

      return info;
    });

    console.log('\n========== Metrics Page Audit ==========');
    console.log(`Page height: ${metricsInfo.pageHeight}px (viewport: ${metricsInfo.viewportHeight}px)`);
    console.log(`Scroll ratio: ${(metricsInfo.pageHeight / metricsInfo.viewportHeight).toFixed(1)}x viewport`);
    console.log(`\nCards (${metricsInfo.cards.length}):`);
    metricsInfo.cards.slice(0, 5).forEach((c) => {
      console.log(`  - ${c.size}: ${c.class}`);
    });
    console.log(`\nSections: ${metricsInfo.sections.join(', ')}`);
    console.log('='.repeat(50));

    // Metrics page should have content
    expect(metricsInfo.pageHeight, 'Metrics page should have content').toBeGreaterThan(0);
  });
});

// ============================================
// MOBILE NAV AUDIT
// ============================================

test.describe('Mobile UI Audit - Navigation', () => {
  test('Mobile bottom nav audit', async ({ page, isMobile }) => {
    if (!isMobile) {
      test.skip();
      return;
    }

    await page.goto('/');
    await page.waitForLoadState('domcontentloaded');

    const navInfo = await page.evaluate(() => {
      const nav = document.querySelector('.ldr-mobile-bottom-nav');
      if (!nav) return { found: false };

      const rect = nav.getBoundingClientRect();
      const style = window.getComputedStyle(nav);

      const items = [];
      nav.querySelectorAll('a, button').forEach((item) => {
        const itemRect = item.getBoundingClientRect();
        items.push({
          text: item.textContent.trim(),
          size: `${Math.round(itemRect.width)}x${Math.round(itemRect.height)}`,
          href: item.getAttribute('href'),
        });
      });

      return {
        found: true,
        position: style.position,
        bottom: style.bottom,
        size: `${Math.round(rect.width)}x${Math.round(rect.height)}`,
        location: `y=${Math.round(rect.y)}`,
        items,
      };
    });

    console.log('\n========== Mobile Nav Audit ==========');
    if (navInfo.found) {
      console.log(`Position: ${navInfo.position}, bottom: ${navInfo.bottom}`);
      console.log(`Size: ${navInfo.size}, Location: ${navInfo.location}`);
      console.log(`\nNav Items (${navInfo.items.length}):`);
      navInfo.items.forEach((item) => {
        console.log(`  - ${item.size}: "${item.text}" -> ${item.href}`);
      });
    } else {
      console.log('Mobile nav not found!');
    }
    console.log('='.repeat(50));

    // Mobile nav assertions
    expect(navInfo.found, 'Mobile bottom nav should exist').toBe(true);

    if (navInfo.found) {
      expect(navInfo.items.length, 'Mobile nav should have items').toBeGreaterThan(0);
      expect(navInfo.position, 'Mobile nav should be fixed').toBe('fixed');
      expect(navInfo.bottom, 'Mobile nav at bottom').toBe('0px');

      const smallNavItems = navInfo.items.filter(item => {
        const [width, height] = item.size.split('x').map(Number);
        return width < 44 || height < 44;
      });

      expect(smallNavItems.length, 'All nav items should meet 44px touch target').toBe(0);
    }
  });
});
