/**
 * Untested Subpages Tests
 *
 * Tests for pages that have zero test coverage:
 * 1. /benchmark/results - Benchmark results page
 * 2. /auth/change-password - Change password form
 *
 * Covers mobile + desktop: page load, overflow, touch targets, screenshots.
 *
 * Note: Authentication is handled by auth.setup.js via storageState
 */

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

// ============================================
// BENCHMARK RESULTS PAGE
// ============================================

test.describe('Benchmark Results Page', () => {
  test.beforeEach(async ({ page }) => {
    await page.goto('/benchmark/results');
    await page.waitForLoadState('domcontentloaded');
  });

  test('page loads without critical errors', async ({ page }) => {
    const errors = [];
    const pageErrors = [];

    // Set up listeners BEFORE navigation
    page.on('console', (msg) => {
      if (msg.type() === 'error') {
        errors.push(msg.text());
      }
    });
    page.on('pageerror', (error) => {
      pageErrors.push(error.message);
    });

    // Navigate fresh to capture all errors. The describe-scoped beforeEach
    // also navigated to this URL — the in-flight history fetch from that
    // navigation can be aborted by this re-navigation and surface as a
    // benign `TypeError: Failed to fetch`. We filter it below.
    await page.goto('/benchmark/results');
    await page.waitForLoadState('domcontentloaded');

    const criticalErrors = errors.filter(
      (err) =>
        !err.includes('favicon') &&
        !err.includes('404') &&
        !err.includes('Failed to load resource') &&
        !err.includes('Failed to fetch') && // benign navigation-abort race
        !err.includes("Can't find variable: Chart") &&
        !err.includes("Can't find variable: io")
    );

    // Filter out known benign page errors (Chart.js and Socket.IO race conditions)
    const criticalPageErrors = pageErrors.filter(
      (err) =>
        !err.includes('Chart') &&
        !err.includes('io') &&
        !err.includes('socket') &&
        !err.includes('is not defined')
    );

    expect(criticalPageErrors.length, `Should have no critical page errors: ${pageErrors.join(', ')}`).toBe(0);
    expect(
      criticalErrors.length,
      `Should have no critical console errors: ${criticalErrors.join(', ')}`
    ).toBe(0);
  });

  test('has no horizontal overflow', async ({ page }) => {
    const hasOverflow = await page.evaluate(() =>
      document.documentElement.scrollWidth > window.innerWidth
    );

    if (hasOverflow) {
      const overflowInfo = await page.evaluate(() => {
        const elements = [];
        document.querySelectorAll('*').forEach((el) => {
          const rect = el.getBoundingClientRect();
          if (rect.right > window.innerWidth) {
            elements.push({
              tag: el.tagName.toLowerCase(),
              class: el.className?.toString().slice(0, 60),
              width: Math.round(rect.width),
              right: Math.round(rect.right),
              overflow: Math.round(rect.right - window.innerWidth),
            });
          }
        });
        return elements.slice(0, 5);
      });
      console.log('Benchmark results overflow:', JSON.stringify(overflowInfo, null, 2));
    }

    expect(hasOverflow, 'Benchmark results should have no horizontal overflow').toBe(false);
  });

  test('mobile nav visible on phone', async ({ page, isMobile }, testInfo) => {
    if (!isMobile) {
      test.skip();
      return;
    }

    const isTablet = testInfo.project.name.includes('iPad');
    if (isTablet) {
      test.skip();
      return;
    }

    const mobileNav = page.locator(MOBILE_NAV_SELECTOR);
    await expect(mobileNav, 'Mobile nav should be visible').toBeVisible();
  });

  test('touch targets >= 44px on mobile', async ({ page, isMobile }, testInfo) => {
    if (!isMobile) {
      test.skip();
      return;
    }

    const isTablet = testInfo.project.name.includes('iPad');
    if (isTablet) {
      test.skip();
      return;
    }

    const smallTargets = await page.evaluate((MIN_SIZE) => {
      const elements = document.querySelectorAll(
        'button, a, input, select, textarea, [role="button"], .btn'
      );
      const issues = [];

      elements.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;
        if (rect.top > window.innerHeight || rect.bottom < 0) return;
        if (rect.left > window.innerWidth || rect.right < 0) return;

        if (rect.width < MIN_SIZE || rect.height < MIN_SIZE) {
          issues.push({
            tag: el.tagName.toLowerCase(),
            class: el.className?.toString().slice(0, 50),
            size: `${Math.round(rect.width)}x${Math.round(rect.height)}`,
            text: (el.textContent || '').trim().slice(0, 30),
          });
        }
      });

      return issues;
    }, MIN_TOUCH_TARGET);

    if (smallTargets.length > 0) {
      console.log('Benchmark results small touch targets:', JSON.stringify(smallTargets, null, 2));
    }

    expect(
      smallTargets.length,
      'Benchmark results should have minimal small touch targets'
    ).toBeLessThan(3);
  });

  test('content not hidden behind mobile nav', async ({ page, isMobile }, testInfo) => {
    if (!isMobile) {
      test.skip();
      return;
    }

    const isTablet = testInfo.project.name.includes('iPad');
    if (isTablet) {
      test.skip();
      return;
    }

    // Scroll to bottom
    await page.evaluate(() => window.scrollTo(0, document.body.scrollHeight));
    await page.waitForTimeout(200);

    const result = await page.evaluate((navSelector) => {
      const mobileNav = document.querySelector(navSelector);
      if (!mobileNav) return { hasNav: false };

      const navStyle = window.getComputedStyle(mobileNav);
      if (navStyle.display === 'none') return { hasNav: false };

      const navRect = mobileNav.getBoundingClientRect();
      const interactiveElements = document.querySelectorAll(
        'button, a, input, select, textarea, [role="button"]'
      );
      const hiddenElements = [];

      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;
        if (el.closest('.ldr-help-panel-dismiss')) return;

        const OVERLAP_TOLERANCE = 20;
        if (rect.bottom > navRect.top + OVERLAP_TOLERANCE && rect.top < navRect.bottom) {
          if (!mobileNav.contains(el)) {
            hiddenElements.push({
              tag: el.tagName.toLowerCase(),
              text: (el.textContent || '').trim().slice(0, 30),
              bottom: Math.round(rect.bottom),
              navTop: Math.round(navRect.top),
            });
          }
        }
      });

      return { hasNav: true, hiddenElements };
    }, MOBILE_NAV_SELECTOR);

    expect(
      result.hiddenElements?.length || 0,
      'Benchmark results should have no elements behind mobile nav'
    ).toBe(0);
  });

  test('filter section renders correctly', async ({ page }) => {
    // Check if there's a filter/controls section on the results page
    const filterSection = page.locator(
      '.ldr-filter, .ldr-controls, [class*="filter"], [class*="controls"], form'
    );
    const hasFilters = await filterSection.count() > 0;

    if (hasFilters) {
      const firstFilter = filterSection.first();
      if (await firstFilter.isVisible()) {
        const box = await firstFilter.boundingBox();
        const viewportWidth = await page.evaluate(() => window.innerWidth);

        if (box) {
          // Filter section should fit within viewport
          expect(
            box.x + box.width,
            'Filter section should not overflow viewport'
          ).toBeLessThanOrEqual(viewportWidth + 5);
        }
      }
    }
  });

  test('mobile screenshot', async ({ page, isMobile }) => {
    if (!isMobile) {
      test.skip();
      return;
    }

    await ensureSheetsClosed(page);
    await page.evaluate(() => window.scrollTo(0, 0));
    await page.waitForTimeout(200);

    await expect(page).toHaveScreenshot('benchmark-results-mobile.png', {
      fullPage: false,
      maxDiffPixelRatio: 0.02,
    });
  });

  test('desktop screenshot', async ({ page, isMobile }) => {
    if (isMobile) {
      test.skip();
      return;
    }

    await page.setViewportSize({ width: 1200, height: 800 });
    await page.goto('/benchmark/results');
    await page.waitForLoadState('domcontentloaded');
    await page.waitForTimeout(200);

    await expect(page).toHaveScreenshot('benchmark-results-desktop.png', {
      maxDiffPixelRatio: 0.02,
    });
  });
});

// ============================================
// CHANGE PASSWORD PAGE
// ============================================

test.describe('Change Password Page', () => {
  test.beforeEach(async ({ page }) => {
    await page.goto('/auth/change-password');
    await page.waitForLoadState('domcontentloaded');
  });

  test('page loads without critical errors', async ({ page }) => {
    const errors = [];
    const pageErrors = [];

    page.on('console', (msg) => {
      if (msg.type() === 'error') {
        errors.push(msg.text());
      }
    });
    page.on('pageerror', (error) => {
      pageErrors.push(error.message);
    });

    await page.goto('/auth/change-password');
    await page.waitForLoadState('domcontentloaded');

    const criticalErrors = errors.filter(
      (err) =>
        !err.includes('favicon') &&
        !err.includes('404') &&
        !err.includes('Failed to load resource')
    );

    const criticalPageErrors = pageErrors.filter(
      (err) =>
        !err.includes('Chart') &&
        !err.includes('io') &&
        !err.includes('socket') &&
        !err.includes('is not defined')
    );

    expect(criticalPageErrors.length, `Should have no critical page errors: ${pageErrors.join(', ')}`).toBe(0);
    expect(
      criticalErrors.length,
      `Should have no critical console errors: ${criticalErrors.join(', ')}`
    ).toBe(0);
  });

  test('form centered and fits viewport', async ({ page }) => {
    const form = page.locator('form').first();

    if (await form.count() > 0 && await form.isVisible()) {
      const formBox = await form.boundingBox();
      const viewportWidth = await page.evaluate(() => window.innerWidth);

      if (formBox) {
        // Form should fit within viewport
        expect(
          formBox.x + formBox.width,
          'Form should fit within viewport'
        ).toBeLessThanOrEqual(viewportWidth + 5);

        // Form should have some margin (be centered, not flush to edge)
        expect(formBox.x, 'Form should not be flush to left edge').toBeGreaterThanOrEqual(0);
      }
    }
  });

  test('password inputs properly sized on mobile', async ({ page, isMobile }, testInfo) => {
    if (!isMobile) {
      test.skip();
      return;
    }

    const isTablet = testInfo.project.name.includes('iPad');
    if (isTablet) {
      test.skip();
      return;
    }

    const passwordInputs = page.locator('input[type="password"]:visible');
    const count = await passwordInputs.count();

    for (let i = 0; i < count; i++) {
      const input = passwordInputs.nth(i);
      const box = await input.boundingBox().catch(() => null);

      if (box) {
        // Password inputs should be at least 44px tall for touch
        expect(box.height, `Password input ${i} height >= 44px`).toBeGreaterThanOrEqual(MIN_TOUCH_TARGET);

        // Font size >= 16px to prevent iOS auto-zoom
        const fontSize = await input.evaluate((el) =>
          parseFloat(window.getComputedStyle(el).fontSize)
        );
        expect(fontSize, `Password input ${i} font size >= 16px`).toBeGreaterThanOrEqual(16);
      }
    }
  });

  test('has no horizontal overflow', async ({ page }) => {
    const hasOverflow = await page.evaluate(() =>
      document.documentElement.scrollWidth > window.innerWidth
    );

    expect(hasOverflow, 'Change password page should have no horizontal overflow').toBe(false);
  });

  test('mobile screenshot', async ({ page, isMobile }) => {
    if (!isMobile) {
      test.skip();
      return;
    }

    await ensureSheetsClosed(page);
    await page.evaluate(() => window.scrollTo(0, 0));
    await page.waitForTimeout(200);

    await expect(page).toHaveScreenshot('change-password-mobile.png', {
      fullPage: false,
      maxDiffPixelRatio: 0.02,
    });
  });

  test('desktop screenshot', async ({ page, isMobile }) => {
    if (isMobile) {
      test.skip();
      return;
    }

    await page.setViewportSize({ width: 1200, height: 800 });
    await page.goto('/auth/change-password');
    await page.waitForLoadState('domcontentloaded');
    await page.waitForTimeout(200);

    await expect(page).toHaveScreenshot('change-password-desktop.png', {
      maxDiffPixelRatio: 0.02,
    });
  });
});
