/**
 * News Subpages Mobile Tests
 *
 * Tests for news subpages on mobile devices:
 * 1. /news/subscriptions - Subscriptions list
 * 2. /news/subscriptions/new - New subscription form
 *
 * Covers:
 * - Page load and error detection
 * - Horizontal overflow
 * - Mobile nav visibility
 * - Touch targets
 * - Content not hidden behind nav
 * - Visual regression screenshots
 * - Page-specific elements
 */

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

const NEWS_SUBPAGES = [
  { path: '/news/subscriptions', name: 'Subscriptions List' },
  { path: '/news/subscriptions/new', name: 'New Subscription' },
];

// ============================================
// COMMON TESTS FOR ALL NEWS SUBPAGES
// ============================================

test.describe('News Subpages - Common Mobile Tests', () => {
  for (const pageInfo of NEWS_SUBPAGES) {
    test.describe(`${pageInfo.name}`, () => {
      test('page loads without errors', async ({ page }) => {
        const errors = [];
        page.on('console', (msg) => {
          if (msg.type() === 'error') {
            errors.push(msg.text());
          }
        });

        const pageErrors = [];
        page.on('pageerror', (error) => {
          pageErrors.push(error.message);
        });

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

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

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

      test('has no horizontal overflow', async ({ page }) => {
        await page.goto(pageInfo.path);
        await page.waitForLoadState('domcontentloaded');

        const hasOverflow = await page.evaluate(() =>
          document.documentElement.scrollWidth > window.innerWidth
        );

        expect(hasOverflow, `${pageInfo.name} should have no horizontal overflow`).toBe(false);
      });

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

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

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

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

      test('has adequate touch targets', async ({ page, isMobile }, testInfo) => {
        if (!isMobile) {
          test.skip();
          return;
        }

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

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

        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(`${pageInfo.name} small touch targets:`, JSON.stringify(smallTargets, null, 2));
        }

        expect(
          smallTargets.length,
          `${pageInfo.name} should have minimal small touch targets`
        ).toBeLessThan(4);
      });

      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;
        }

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

        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;

            const OVERLAP_TOLERANCE = 5;
            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),
                });
              }
            }
          });

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

        if ((result.hiddenElements?.length || 0) > 0) {
          console.log(`${pageInfo.name} has elements behind mobile nav:`, JSON.stringify(result.hiddenElements));
        }

        // Allow up to 5 elements (form pages may have multiple action buttons near bottom)
        expect(
          result.hiddenElements?.length || 0,
          `${pageInfo.name} should have minimal elements behind mobile nav`
        ).toBeLessThan(6);
      });

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

        await page.goto(pageInfo.path);
        await page.waitForLoadState('domcontentloaded');
        await ensureSheetsClosed(page);
        await page.evaluate(() => window.scrollTo(0, 0));
        await page.waitForTimeout(200);

        const safeName = pageInfo.name.toLowerCase().replace(/[^a-z0-9]/g, '-');

        await expect(page).toHaveScreenshot(`news-${safeName}-viewport.png`, {
          fullPage: false,
          maxDiffPixelRatio: 0.02,
        });
      });
    });
  }
});

// ============================================
// SUBSCRIPTIONS LIST - SPECIFIC TESTS
// ============================================

test.describe('Subscriptions List - Specific Tests', () => {
  test.beforeEach(async ({ page }) => {
    await page.goto('/news/subscriptions');
    await page.waitForLoadState('domcontentloaded');
  });

  test('page content loads', async ({ page }) => {
    // Verify the page has rendered some content
    const content = page.locator('.ldr-main-content, main, body');
    await expect(content.first()).toBeVisible();

    // Check there's meaningful content (not just an empty shell)
    const textContent = await page.evaluate(() => document.body.innerText.trim().length);
    expect(textContent, 'Page should have text content').toBeGreaterThan(10);
  });

  test('subscription list or empty state visible', async ({ page }) => {
    // Either show subscription cards or an empty state message
    const subscriptionList = page.locator('.ldr-subscription-card, .ldr-subscription-item, [class*="subscription"]');
    const emptyState = page.locator('.ldr-empty-state, [class*="empty"], [class*="no-data"]');
    const pageContent = page.locator('.ldr-main-content, main');

    const hasSubscriptions = await subscriptionList.count() > 0;
    const hasEmptyState = await emptyState.count() > 0;
    const hasContent = await pageContent.count() > 0;

    expect(hasSubscriptions || hasEmptyState || hasContent, 'Should show subscriptions, empty state, or page content').toBe(true);
  });

  test('subscription cards fit viewport on mobile', async ({ page, isMobile }) => {
    if (!isMobile) {
      test.skip();
      return;
    }

    const cards = page.locator('.ldr-subscription-card, .card, [class*="subscription-card"]');
    const count = await cards.count();
    const viewportWidth = await page.evaluate(() => window.innerWidth);

    for (let i = 0; i < count; i++) {
      const card = cards.nth(i);
      if (await card.isVisible()) {
        const box = await card.boundingBox();
        if (box) {
          expect(box.width, `Subscription card ${i} should fit viewport`).toBeLessThanOrEqual(viewportWidth);
        }
      }
    }
  });
});

// ============================================
// NEW SUBSCRIPTION FORM - SPECIFIC TESTS
// ============================================

test.describe('New Subscription Form - Specific Tests', () => {
  test.beforeEach(async ({ page }) => {
    await page.goto('/news/subscriptions/new');
    await page.waitForLoadState('domcontentloaded');
  });

  test('displays form elements', async ({ page }) => {
    // Check for form or form-like content
    const form = page.locator('form').first();
    const inputs = page.locator('input:not([type="hidden"]), textarea, select');

    const hasForm = await form.count() > 0;
    const hasInputs = await inputs.count() > 0;

    expect(hasForm || hasInputs, 'Should display form elements').toBe(true);
  });

  test('form inputs have proper sizing on mobile', async ({ page, isMobile }, testInfo) => {
    if (!isMobile) {
      test.skip();
      return;
    }

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

    const inputs = page.locator('input:not([type="hidden"]):visible, select:visible, textarea:visible');
    const count = await inputs.count();
    const viewportWidth = await page.evaluate(() => window.innerWidth);

    for (let i = 0; i < Math.min(count, 15); i++) {
      const input = inputs.nth(i);
      const box = await input.boundingBox().catch(() => null);

      if (box) {
        // Inputs should not overflow viewport
        expect(box.x + box.width, `Input ${i} should fit viewport`).toBeLessThanOrEqual(viewportWidth + 5);
        // Font size should be at least 16px to prevent iOS zoom
        const fontSize = await input.evaluate((el) => parseFloat(window.getComputedStyle(el).fontSize));
        expect(fontSize, `Input ${i} font size >= 16px`).toBeGreaterThanOrEqual(16);
      }
    }
  });

  test('submit button is accessible', async ({ page, isMobile }) => {
    const submitBtn = page.locator('button[type="submit"], button:has-text("Create"), button:has-text("Save"), button:has-text("Subscribe")').first();

    if (await submitBtn.count() > 0) {
      await expect(submitBtn).toBeVisible();

      if (isMobile) {
        const box = await submitBtn.boundingBox();
        if (box) {
          expect(box.height, 'Submit button height >= 44px').toBeGreaterThanOrEqual(MIN_TOUCH_TARGET);
        }
      }
    }
  });

  test('template cards are touch-friendly on mobile', async ({ page, isMobile }, testInfo) => {
    if (!isMobile) {
      test.skip();
      return;
    }

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

    const templates = page.locator('.ldr-template-card, [class*="template"]');
    const count = await templates.count();

    for (let i = 0; i < Math.min(count, 10); i++) {
      const template = templates.nth(i);
      if (await template.isVisible()) {
        const box = await template.boundingBox();
        if (box) {
          expect(box.height, `Template ${i} height >= 44px`).toBeGreaterThanOrEqual(MIN_TOUCH_TARGET);
        }
      }
    }
  });

  test('form 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('news-new-subscription-form.png', {
      fullPage: false,
      maxDiffPixelRatio: 0.02,
    });
  });
});
