/**
 * Metrics Subpages Mobile Tests
 *
 * Specific component and functionality tests for metrics subpages on mobile devices.
 * These tests verify page-specific elements, navigation, and mobile responsiveness.
 *
 * Subpages tested:
 * 1. /metrics/context-overflow - Context Overflow Analytics
 * 2. /metrics/star-reviews - Star Reviews Analytics
 * 3. /metrics/costs - Cost Analytics
 * 4. /metrics/links - Link Analytics Dashboard
 */

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

// Metrics subpages configuration
const METRICS_SUBPAGES = [
  { path: '/metrics/context-overflow', name: 'Context Overflow', header: 'Context Overflow Analytics' },
  { path: '/metrics/star-reviews', name: 'Star Reviews', header: 'Star Reviews Analytics' },
  { path: '/metrics/costs', name: 'Cost Analytics', header: 'Cost Analytics' },
  { path: '/metrics/links', name: 'Link Analytics', header: 'Link Analytics Dashboard' },
];

// ============================================
// COMMON TESTS FOR ALL METRICS SUBPAGES
// ============================================

test.describe('Metrics Subpages - Common Mobile Tests', () => {
  for (const pageInfo of METRICS_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') &&
            !err.includes("Can't find variable: Chart") && // Chart.js loading timing
            !err.includes('Chart is not defined') // Chart.js loading timing
        );

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

        // Skip on tablets - they use sidebar
        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;
        }

        // Skip on tablets
        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);

        // Allow up to 3 small elements
        expect(
          smallTargets.length,
          `${pageInfo.name} should have minimal small touch targets`
        ).toBeLessThan(3);
      });

      test('Back to Metrics button is visible and tappable', async ({ page, isMobile }) => {
        await page.goto(pageInfo.path);
        await page.waitForLoadState('domcontentloaded');

        // Find the Back to Metrics link/button
        const backButton = page.locator('a:has-text("Back to Metrics"), button:has-text("Back to Metrics")').first();

        await expect(backButton, 'Back to Metrics button should be visible').toBeVisible();

        // Check touch target size on mobile
        if (isMobile) {
          const box = await backButton.boundingBox();
          expect(box).toBeTruthy();
          expect(box.height, 'Back button should have adequate height').toBeGreaterThanOrEqual(32);
        }

        // Click and verify navigation
        await backButton.click();
        await page.waitForLoadState('domcontentloaded');

        expect(page.url()).toContain('/metrics');
        expect(page.url()).not.toContain(pageInfo.path.replace('/metrics/', ''));
      });

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

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

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

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

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

        expect(
          result.hiddenElements?.length || 0,
          `${pageInfo.name} should have no elements behind mobile nav`
        ).toBe(0);
      });

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

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

        // Scroll to top
        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(`metrics-${safeName}-viewport.png`, {
          fullPage: false,
          maxDiffPixelRatio: 0.02,
        });
      });
    });
  }
});

// ============================================
// CONTEXT OVERFLOW PAGE SPECIFIC TESTS
// ============================================

test.describe('Context Overflow Page - Specific Tests', () => {
  test.beforeEach(async ({ page }) => {
    await page.goto('/metrics/context-overflow');
    await page.waitForLoadState('domcontentloaded');
  });

  test('displays page header correctly', async ({ page }) => {
    const header = page.locator('h1:has-text("Context Overflow Analytics")');
    await expect(header).toBeVisible();
  });

  test('time range selector is visible', async ({ page, isMobile }) => {
    const timeRangeSelector = page.locator('.ldr-time-range-selector');
    await expect(timeRangeSelector).toBeVisible();

    // Check time range buttons
    const buttons = ['7D', '30D', '3M', '1Y', 'All'];
    for (const label of buttons) {
      const btn = page.locator(`.ldr-time-range-btn:has-text("${label}")`);
      await expect(btn, `${label} button should be visible`).toBeVisible();
    }

    // 30D should be active by default
    const activeBtn = page.locator('.ldr-time-range-btn.active');
    await expect(activeBtn).toHaveText('30D');
  });

  test('overview cards present after loading', async ({ page }) => {
    // Wait for loading to complete
    await page.waitForSelector('#loading', { state: 'hidden', timeout: 10000 }).catch(() => {});
    await page.waitForSelector('#content', { state: 'visible', timeout: 10000 }).catch(() => {});

    // Check for overview cards
    const overflowGrid = page.locator('.ldr-overflow-grid');
    if (await overflowGrid.isVisible()) {
      const cards = overflowGrid.locator('.ldr-overflow-card');
      const count = await cards.count();
      expect(count).toBeGreaterThanOrEqual(4);

      // Check specific metrics labels
      await expect(page.locator('#truncation-rate')).toBeVisible();
      await expect(page.locator('#avg-tokens-lost')).toBeVisible();
      await expect(page.locator('#models-tracked')).toBeVisible();
      await expect(page.locator('#data-coverage')).toBeVisible();
    }
  });

  test('help panel is expandable', async ({ page }) => {
    const helpPanel = page.locator('[id*="context-how"], .ldr-help-panel').first();
    if (await helpPanel.count() > 0) {
      await expect(helpPanel).toBeVisible();
    }
  });

  test('time range button is tappable', async ({ page, isMobile }) => {
    if (!isMobile) {
      test.skip();
      return;
    }

    const btn7d = page.locator('.ldr-time-range-btn:has-text("7D")');
    await expect(btn7d).toBeVisible();

    // Click to change time range
    await btn7d.click();
    await btn7d.waitFor({ state: 'attached' });

    // Should now be active
    await expect(btn7d).toHaveClass(/active/);
  });
});

// ============================================
// STAR REVIEWS PAGE SPECIFIC TESTS
// ============================================

test.describe('Star Reviews Page - Specific Tests', () => {
  test.beforeEach(async ({ page }) => {
    await page.goto('/metrics/star-reviews');
    await page.waitForLoadState('domcontentloaded');
  });

  test('displays page header correctly', async ({ page }) => {
    const header = page.locator('h1:has-text("Star Reviews")');
    await expect(header).toBeVisible();
  });

  test('time period dropdown is visible', async ({ page }) => {
    const periodSelector = page.locator('.ldr-period-selector select, select[id*="period"]').first();
    if (await periodSelector.count() > 0) {
      await expect(periodSelector).toBeVisible();
    }
  });

  test('overall stats section visible after loading', async ({ page }) => {
    await page.waitForSelector('.ldr-metric-card, .ldr-chart, canvas, .ldr-metrics-content', { timeout: 15000 }).catch(() => {});

    const statsSection = page.locator('.ldr-overall-stats');
    if (await statsSection.count() > 0 && await statsSection.isVisible()) {
      // Check for stat items
      const statItems = statsSection.locator('.ldr-stat-item');
      const count = await statItems.count();
      expect(count).toBeGreaterThanOrEqual(1);
    }
  });

  test('rating distribution bars visible', async ({ page }) => {
    await page.waitForSelector('.ldr-metric-card, .ldr-chart, canvas, .ldr-metrics-content', { timeout: 15000 }).catch(() => {});

    const ratingDistribution = page.locator('.ldr-rating-distribution, .ldr-rating-bar').first();
    if (await ratingDistribution.count() > 0) {
      await expect(ratingDistribution).toBeVisible();
    }
  });

  test('charts containers present', async ({ page }) => {
    await page.waitForSelector('.ldr-metric-card, .ldr-chart, canvas, .ldr-metrics-content', { timeout: 15000 }).catch(() => {});

    // Check for chart containers
    const chartContainers = page.locator('.ldr-chart-container, .ldr-metric-card canvas').first();
    if (await chartContainers.count() > 0) {
      await expect(chartContainers).toBeVisible();
    }
  });
});

// ============================================
// COST ANALYTICS PAGE SPECIFIC TESTS
// ============================================

test.describe('Cost Analytics Page - Specific Tests', () => {
  test.beforeEach(async ({ page }) => {
    await page.goto('/metrics/costs');
    await page.waitForLoadState('domcontentloaded');
  });

  test('displays page header correctly', async ({ page }) => {
    const header = page.locator('h1:has-text("Cost Analytics"), .ldr-cost-title h1');
    await expect(header.first()).toBeVisible();
  });

  test('back button visible', async ({ page }) => {
    const backButton = page.locator('.ldr-back-button, a:has-text("Back to Metrics")').first();
    await expect(backButton).toBeVisible();
  });

  test('help panel expandable if present', async ({ page }) => {
    const helpPanel = page.locator('.ldr-help-panel').first();
    if (await helpPanel.count() > 0) {
      await expect(helpPanel).toBeVisible();
    }
  });

  test('shows content or disabled state', async ({ page }) => {
    // Cost analytics may show a disabled message or content grid
    await page.waitForSelector('.ldr-metric-card, .ldr-chart, canvas, .ldr-metrics-content', { timeout: 15000 }).catch(() => {});

    // Check if any content is visible (either enabled content or disabled message)
    const contentGrid = page.locator('.ldr-cost-grid');
    const costCard = page.locator('.ldr-cost-card');
    const disabledMsg = page.locator('[class*="disabled"], [class*="no-data"], .ldr-empty-state');
    const pageContent = page.locator('.ldr-cost-analytics-container, #content');

    // At least one of these should be visible
    const hasGrid = await contentGrid.count() > 0 && await contentGrid.first().isVisible().catch(() => false);
    const hasCard = await costCard.count() > 0 && await costCard.first().isVisible().catch(() => false);
    const hasDisabled = await disabledMsg.count() > 0 && await disabledMsg.first().isVisible().catch(() => false);
    const hasPageContent = await pageContent.count() > 0 && await pageContent.first().isVisible().catch(() => false);

    expect(
      hasGrid || hasCard || hasDisabled || hasPageContent,
      'Cost Analytics should show content or disabled state'
    ).toBe(true);
  });

  test('time range selector if enabled', async ({ page }) => {
    const timeRangeSelector = page.locator('.ldr-time-range-selector');
    if (await timeRangeSelector.count() > 0 && await timeRangeSelector.isVisible()) {
      const buttons = timeRangeSelector.locator('.ldr-time-range-btn');
      const count = await buttons.count();
      expect(count).toBeGreaterThan(0);
    }
  });
});

// ============================================
// LINK ANALYTICS PAGE SPECIFIC TESTS
// ============================================

test.describe('Link Analytics Page - Specific Tests', () => {
  test.beforeEach(async ({ page }) => {
    await page.goto('/metrics/links');
    await page.waitForLoadState('domcontentloaded');
  });

  test('displays page header correctly', async ({ page }) => {
    const header = page.locator('h1:has-text("Link Analytics")');
    await expect(header).toBeVisible();
  });

  test('Classify Domains button visible', async ({ page }) => {
    const classifyBtn = page.locator('button:has-text("Classify"), a:has-text("Classify")').first();
    if (await classifyBtn.count() > 0) {
      await expect(classifyBtn).toBeVisible();
    }
  });

  test('overall stats cards visible after loading', async ({ page }) => {
    await page.waitForSelector('.ldr-metric-card, .ldr-chart, canvas, .ldr-metrics-content', { timeout: 15000 }).catch(() => {});

    const statsSection = page.locator('.ldr-overall-stats');
    if (await statsSection.count() > 0 && await statsSection.isVisible()) {
      const statItems = statsSection.locator('.ldr-stat-item');
      const count = await statItems.count();
      expect(count).toBeGreaterThanOrEqual(1);
    }
  });

  test('charts or metric cards present', async ({ page }) => {
    await page.waitForSelector('.ldr-metric-card, .ldr-chart, canvas, .ldr-metrics-content', { timeout: 15000 }).catch(() => {});

    // Look for chart containers or metric cards - check if any are visible
    const chartContainers = page.locator('.ldr-chart-container:visible, .ldr-metric-card:visible');
    const count = await chartContainers.count();

    // At least verify the page loaded - charts may or may not be visible depending on data
    const pageLoaded = await page.locator('.ldr-link-analytics-container, .ldr-overall-stats').first().isVisible().catch(() => false);
    expect(pageLoaded || count > 0, 'Page should show charts or main content').toBe(true);
  });

  test('page has main content container', async ({ page }) => {
    await page.waitForSelector('.ldr-metric-card, .ldr-chart, canvas, .ldr-metrics-content', { timeout: 15000 }).catch(() => {});

    // Check that the page has main content - either domain list, charts, or stats
    const mainContainer = page.locator('.ldr-link-analytics-container, .ldr-metrics-grid, .ldr-overall-stats').first();
    if (await mainContainer.count() > 0) {
      await expect(mainContainer).toBeVisible();
    }
  });

  test('time period selector if present', async ({ page }) => {
    const periodSelector = page.locator('.ldr-period-selector, select[id*="period"]').first();
    if (await periodSelector.count() > 0 && await periodSelector.isVisible()) {
      await expect(periodSelector).toBeVisible();
    }
  });
});

// ============================================
// COMPONENT SCREENSHOT TESTS
// ============================================

test.describe('Metrics Subpages - Component Screenshots', () => {
  test('Context Overflow - Overview cards', async ({ page, isMobile }) => {
    if (!isMobile) {
      test.skip();
      return;
    }

    await page.goto('/metrics/context-overflow');
    await page.waitForLoadState('domcontentloaded');
    await page.waitForSelector('#loading', { state: 'hidden', timeout: 10000 }).catch(() => {});
    await ensureSheetsClosed(page);

    const overflowGrid = page.locator('.ldr-overflow-grid').first();
    if (await overflowGrid.isVisible()) {
      await expect(overflowGrid).toHaveScreenshot('context-overflow-cards.png', {
        maxDiffPixelRatio: 0.02,
      });
    }
  });

  test('Star Reviews - Stats section', async ({ page, isMobile }) => {
    if (!isMobile) {
      test.skip();
      return;
    }

    await page.goto('/metrics/star-reviews');
    await page.waitForLoadState('domcontentloaded');
    await page.waitForSelector('.ldr-metric-card, .ldr-chart, canvas, .ldr-metrics-content', { timeout: 15000 }).catch(() => {});
    await ensureSheetsClosed(page);

    const statsSection = page.locator('.ldr-overall-stats').first();
    if (await statsSection.count() > 0 && await statsSection.isVisible()) {
      await expect(statsSection).toHaveScreenshot('star-reviews-stats.png', {
        maxDiffPixelRatio: 0.02,
      });
    }
  });

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

    await page.goto('/metrics/links');
    await page.waitForLoadState('domcontentloaded');
    await page.waitForSelector('.ldr-metric-card, .ldr-chart, canvas, .ldr-metrics-content', { timeout: 15000 }).catch(() => {});
    await ensureSheetsClosed(page);

    const statsSection = page.locator('.ldr-overall-stats').first();
    if (await statsSection.count() > 0 && await statsSection.isVisible()) {
      await expect(statsSection).toHaveScreenshot('link-analytics-stats.png', {
        maxDiffPixelRatio: 0.02,
      });
    }
  });

  test('Cost Analytics - Header section', async ({ page, isMobile }) => {
    if (!isMobile) {
      test.skip();
      return;
    }

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

    const headerSection = page.locator('.ldr-cost-header, .ldr-cost-title').first();
    if (await headerSection.count() > 0 && await headerSection.isVisible()) {
      await expect(headerSection).toHaveScreenshot('cost-analytics-header.png', {
        maxDiffPixelRatio: 0.02,
      });
    }
  });
});
