/**
 * Library Subpages Mobile Tests
 *
 * Tests for library subpages on mobile devices:
 * 1. /library/collections - Collections list
 * 2. /library/collections/create - Create collection form
 * 3. /library/download-manager - Download manager
 * 4. /library/embedding-settings - Embedding settings
 *
 * 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 LIBRARY_SUBPAGES = [
  { path: '/library/collections', name: 'Collections' },
  { path: '/library/collections/create', name: 'Create Collection' },
  { path: '/library/download-manager', name: 'Download Manager' },
  { path: '/library/embedding-settings', name: 'Embedding Settings' },
];

// ============================================
// COMMON TESTS FOR ALL LIBRARY SUBPAGES
// ============================================

test.describe('Library Subpages - Common Mobile Tests', () => {
  for (const pageInfo of LIBRARY_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(`library-${safeName}-viewport.png`, {
          fullPage: false,
          maxDiffPixelRatio: 0.02,
        });
      });
    });
  }
});

// ============================================
// COLLECTIONS PAGE - SPECIFIC TESTS
// ============================================

test.describe('Collections Page - Specific Tests', () => {
  test.beforeEach(async ({ page }) => {
    await page.goto('/library/collections');
    await page.waitForLoadState('domcontentloaded');
  });

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

    const textContent = await page.evaluate(() => document.body.innerText.trim().length);
    expect(textContent, 'Page should have text content').toBeGreaterThan(10);
  });

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

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

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

  test('collection list or empty state visible', async ({ page }) => {
    const collectionList = page.locator('.ldr-collection-card, [class*="collection"]');
    const emptyState = page.locator('.ldr-empty-state, [class*="empty"], [class*="no-data"]');
    const pageContent = page.locator('.ldr-main-content, main');

    const hasCollections = await collectionList.count() > 0;
    const hasEmptyState = await emptyState.count() > 0;
    const hasContent = await pageContent.count() > 0;

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

// ============================================
// CREATE COLLECTION PAGE - SPECIFIC TESTS
// ============================================

test.describe('Create Collection Page - Specific Tests', () => {
  test.beforeEach(async ({ page }) => {
    await page.goto('/library/collections/create');
    await page.waitForLoadState('domcontentloaded');
  });

  test('displays form or creation UI', async ({ page }) => {
    const form = page.locator('form').first();
    const inputs = page.locator('input:not([type="hidden"]), textarea, select');
    const pageContent = page.locator('.ldr-main-content, main');

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

    expect(hasForm || hasInputs || hasContent, 'Should display form or page content').toBe(true);
  });

  test('form inputs fit viewport 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) {
        expect(box.x + box.width, `Input ${i} should fit viewport`).toBeLessThanOrEqual(viewportWidth + 5);
      }
    }
  });

  test('submit/create button accessible', async ({ page, isMobile }) => {
    const submitBtn = page.locator(
      'button[type="submit"], button:has-text("Create"), button:has-text("Save")'
    ).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);
        }
      }
    }
  });
});

// ============================================
// DOWNLOAD MANAGER PAGE - SPECIFIC TESTS
// ============================================

test.describe('Download Manager Page - Specific Tests', () => {
  test.beforeEach(async ({ page }) => {
    await page.goto('/library/download-manager');
    await page.waitForLoadState('domcontentloaded');
  });

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

    const textContent = await page.evaluate(() => document.body.innerText.trim().length);
    expect(textContent, 'Page should have text content').toBeGreaterThan(10);
  });

  test('has main content area', async ({ page }) => {
    const content = page.locator('.ldr-main-content, main, .ldr-download-manager');
    await expect(content.first()).toBeVisible();
  });

  test('action buttons 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 actionButtons = page.locator('button:visible').filter({
      hasText: /Download|Sync|Fetch|Start|Stop|Cancel/i,
    });

    const count = await actionButtons.count();
    for (let i = 0; i < count; i++) {
      const button = actionButtons.nth(i);
      const box = await button.boundingBox();
      if (box) {
        expect(box.height, `Action button ${i} height >= 44px`).toBeGreaterThanOrEqual(MIN_TOUCH_TARGET);
      }
    }
  });

  test('download list or empty state visible', async ({ page }) => {
    const downloadList = page.locator('.ldr-download-item, [class*="download"]');
    const emptyState = page.locator('.ldr-empty-state, [class*="empty"], [class*="no-data"]');
    const pageContent = page.locator('.ldr-main-content, main');

    const hasDownloads = await downloadList.count() > 0;
    const hasEmptyState = await emptyState.count() > 0;
    const hasContent = await pageContent.count() > 0;

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

// ============================================
// EMBEDDING SETTINGS PAGE - SPECIFIC TESTS
// ============================================

test.describe('Embedding Settings Page - Specific Tests', () => {
  test.beforeEach(async ({ page }) => {
    await page.goto('/library/embedding-settings');
    await page.waitForLoadState('domcontentloaded');
  });

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

    const textContent = await page.evaluate(() => document.body.innerText.trim().length);
    expect(textContent, 'Page should have text content').toBeGreaterThan(10);
  });

  test('has settings form or configuration UI', async ({ page }) => {
    const form = page.locator('form').first();
    const inputs = page.locator('input:not([type="hidden"]), textarea, select');
    const pageContent = page.locator('.ldr-main-content, main');

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

    expect(hasForm || hasInputs || hasContent, 'Should display settings form or page content').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 tooSmall = [];
    for (let i = 0; i < Math.min(count, 15); i++) {
      const input = inputs.nth(i);
      const box = await input.boundingBox().catch(() => null);

      if (box && box.height < 32) {
        const name = await input.getAttribute('name').catch(() => '');
        tooSmall.push({ index: i, name, height: box.height });
      }
    }

    expect(tooSmall.length, 'Most inputs should be adequately sized').toBeLessThan(3);
  });

  test('save button accessible', async ({ page, isMobile }, testInfo) => {
    // Skip strict height check on tablets - they have different layout
    const isTablet = testInfo.project.name.includes('iPad');

    const saveBtn = page.locator(
      'button[type="submit"], button:has-text("Save"), button:has-text("Apply")'
    ).first();

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

      if (isMobile && !isTablet) {
        const box = await saveBtn.boundingBox();
        if (box) {
          expect(box.height, 'Save button height >= 44px').toBeGreaterThanOrEqual(MIN_TOUCH_TARGET);
        }
      }
    }
  });
});
