import { test, expect } from '@playwright/test';

/**
 * E2E Blog Navigation Test Suite
 * Comprehensive testing of blog listing, filtering, and post reading flows
 */

test.describe('Blog Navigation - Complete User Flow', () => {
  test('navigate from homepage to blog and read multiple posts', async ({ page }) => {
    // Start from homepage
    await page.goto('/');

    // Navigate to blog
    const blogLink = page.locator('a[href="/blog"]').first();
    await blogLink.click();
    await expect(page).toHaveURL('/blog');

    // Verify blog page loaded
    await page.waitForLoadState('networkidle');
    const posts = page.locator('article, [class*="post"], [class*="card"]');
    const postCount = await posts.count();
    expect(postCount).toBeGreaterThan(0);

    // Click first post
    const firstPost = posts.first().locator('a').first();
    await firstPost.click();
    await expect(page).toHaveURL(/\/blog\//);

    // Verify post content
    await expect(page.locator('h1')).toBeVisible();
    await expect(page.locator('article, [class*="prose"]')).toBeVisible();

    // Navigate back to blog listing
    await page.goBack();
    await expect(page).toHaveURL('/blog');

    // Click different post
    if (postCount > 1) {
      const secondPost = posts.nth(1).locator('a').first();
      await secondPost.click();
      await expect(page).toHaveURL(/\/blog\//);
    }
  });

  test('blog post deep reading experience', async ({ page }) => {
    await page.goto('/blog/getting-started-with-astro');

    // Verify title loaded
    const title = page.locator('h1');
    await expect(title).toBeVisible();

    // Verify content structure
    const article = page.locator('article, [class*="prose"], main').first();
    await expect(article).toBeVisible();

    // Check for paragraphs
    const paragraphs = page.locator('p');
    expect(await paragraphs.count()).toBeGreaterThan(0);

    // Scroll through content
    await page.evaluate(() => window.scrollTo(0, 500));
    await page.waitForTimeout(300);

    await page.evaluate(() => window.scrollTo(0, 1000));
    await page.waitForTimeout(300);

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

    // Verify no layout breaks during scroll
    const bodyWidth = await page.evaluate(() => document.body.scrollWidth);
    const viewportWidth = page.viewportSize()?.width || 1280;
    expect(bodyWidth).toBeLessThanOrEqual(viewportWidth + 20);
  });

  test('blog post metadata visibility', async ({ page }) => {
    await page.goto('/blog');

    const firstPost = page.locator('article, [class*="post"]').first();

    // Check for date/time
    const hasDate = await firstPost.locator('time, [class*="date"]').count() > 0;
    expect(hasDate).toBeTruthy();

    // Click to full post
    await firstPost.locator('a').first().click();
    await expect(page).toHaveURL(/\/blog\//);

    // Verify metadata on post page
    const postDate = page.locator('time, [class*="date"]');
    if (await postDate.count() > 0) {
      await expect(postDate.first()).toBeVisible();
    }
  });

  test('blog image loading and optimization', async ({ page }) => {
    await page.goto('/blog/getting-started-with-astro');

    await page.waitForLoadState('networkidle');

    const images = page.locator('img');
    const imageCount = await images.count();

    if (imageCount > 0) {
      // Check first few images
      for (let i = 0; i < Math.min(3, imageCount); i++) {
        const img = images.nth(i);

        if (await img.isVisible()) {
          // Verify image has loaded
          const loaded = await img.evaluate((el: HTMLImageElement) => {
            return el.complete && el.naturalWidth > 0;
          });
          expect(loaded).toBeTruthy();

          // Check for alt text (accessibility)
          const alt = await img.getAttribute('alt');
          expect(alt).toBeTruthy();
        }
      }
    }
  });

  test('blog category/tag navigation', async ({ page }) => {
    await page.goto('/blog');

    // Look for category badges or tags
    const categories = page.locator('[class*="category"], [class*="tag"], [class*="badge"]');

    if (await categories.count() > 0) {
      // Categories should be visible
      await expect(categories.first()).toBeVisible();

      // If categories are clickable, test navigation
      const firstCategory = categories.first();
      const isLink = (await firstCategory.evaluate(el => el.tagName)) === 'A';

      if (isLink) {
        await firstCategory.click();
        // Should filter or navigate
        await page.waitForLoadState('networkidle');
      }
    }
  });

  test('blog search functionality if available', async ({ page }) => {
    await page.goto('/blog');

    // Check for search input
    const searchInput = page.locator('input[type="search"], input[placeholder*="search" i]');

    if (await searchInput.count() > 0) {
      await searchInput.fill('astro');
      await page.keyboard.press('Enter');

      // Wait for search results
      await page.waitForTimeout(500);

      // Verify some results or "no results" message
      const hasResults = await page.locator('article, [class*="post"]').count() > 0 ||
                        await page.locator('text=/no results|no posts/i').count() > 0;
      expect(hasResults).toBeTruthy();
    }
  });

  test('blog pagination if available', async ({ page }) => {
    await page.goto('/blog');

    // Look for pagination controls
    const paginationNext = page.locator('[class*="pagination"] a, button[class*="next"], a:has-text("Next")');

    if (await paginationNext.count() > 0) {
      const nextButton = paginationNext.first();

      if (await nextButton.isVisible()) {
        await nextButton.click();
        await page.waitForLoadState('networkidle');

        // Should show different posts or page 2
        const hasContent = await page.locator('article, [class*="post"]').count() > 0;
        expect(hasContent).toBeTruthy();
      }
    }
  });
});

test.describe('Blog Navigation - Mobile Experience', () => {
  test.use({ viewport: { width: 375, height: 667 } });

  test('mobile blog listing is readable', async ({ page }) => {
    await page.goto('/blog');

    // Posts should stack vertically
    const posts = page.locator('article, [class*="post"]');
    await expect(posts.first()).toBeVisible();

    // No horizontal scroll
    const bodyWidth = await page.evaluate(() => document.body.scrollWidth);
    expect(bodyWidth).toBeLessThanOrEqual(395);

    // Tap first post
    await posts.first().locator('a').first().tap();
    await expect(page).toHaveURL(/\/blog\//);
  });

  test('mobile blog post reading experience', async ({ page }) => {
    await page.goto('/blog/getting-started-with-astro');

    // Content should be readable
    const content = page.locator('article, [class*="prose"]');
    await expect(content.first()).toBeVisible();

    // No horizontal overflow
    const bodyWidth = await page.evaluate(() => document.body.scrollWidth);
    expect(bodyWidth).toBeLessThanOrEqual(400);

    // Font should be readable
    const fontSize = await page.locator('p').first().evaluate(el => {
      return parseFloat(window.getComputedStyle(el).fontSize);
    });
    expect(fontSize).toBeGreaterThanOrEqual(14);

    // Test scroll performance
    for (let i = 0; i < 5; i++) {
      await page.evaluate(() => window.scrollBy(0, 200));
      await page.waitForTimeout(100);
    }

    // Verify images adapt to mobile
    const images = page.locator('img');
    if (await images.count() > 0) {
      const firstImg = images.first();
      const imgWidth = await firstImg.evaluate(el => el.getBoundingClientRect().width);
      expect(imgWidth).toBeLessThanOrEqual(375);
    }
  });
});

test.describe('Blog Navigation - Reading Patterns', () => {
  test('skimming behavior - quick navigation', async ({ page }) => {
    await page.goto('/blog');

    const posts = page.locator('article, [class*="post"]');
    const postCount = await posts.count();

    // Simulate user skimming multiple posts quickly
    for (let i = 0; i < Math.min(3, postCount); i++) {
      const post = posts.nth(i);
      await post.scrollIntoViewIfNeeded();
      await page.waitForTimeout(200);

      // Check title is visible during skim
      const title = post.locator('h1, h2, h3, [class*="title"]');
      await expect(title).toBeVisible();
    }
  });

  test('deep reading behavior - single post focus', async ({ page }) => {
    await page.goto('/blog/getting-started-with-astro');

    // Simulate reading: scroll slowly through content
    const contentHeight = await page.evaluate(() => document.body.scrollHeight);
    const steps = 10;
    const scrollStep = contentHeight / steps;

    for (let i = 0; i < steps; i++) {
      await page.evaluate((step) => window.scrollTo(0, step), scrollStep * i);
      await page.waitForTimeout(300);

      // Content should remain stable during scroll
      const bodyWidth = await page.evaluate(() => document.body.scrollWidth);
      const viewportWidth = page.viewportSize()?.width || 1280;
      expect(bodyWidth).toBeLessThanOrEqual(viewportWidth + 20);
    }
  });

  test('code block interaction in blog posts', async ({ page }) => {
    await page.goto('/blog/getting-started-with-astro');

    const codeBlocks = page.locator('pre, code, [class*="shiki"]');
    const codeCount = await codeBlocks.count();

    if (codeCount > 0) {
      const firstCodeBlock = codeBlocks.first();
      await firstCodeBlock.scrollIntoViewIfNeeded();

      // Verify code is readable
      await expect(firstCodeBlock).toBeVisible();

      // Check for syntax highlighting
      const hasHighlighting = await firstCodeBlock.locator('[class*="token"], [class*="hl"], span').count() > 0;
      // Syntax highlighting is optional but beneficial
      expect(hasHighlighting || true).toBeTruthy();

      // Verify monospace font
      const fontFamily = await firstCodeBlock.evaluate(el => {
        return window.getComputedStyle(el).fontFamily.toLowerCase();
      });
      expect(fontFamily).toMatch(/mono|consolas|courier|jetbrains/);
    }
  });

  test('blog post sharing and social links', async ({ page }) => {
    await page.goto('/blog/getting-started-with-astro');

    // Look for social share buttons
    const socialLinks = page.locator('a[href*="twitter"], a[href*="linkedin"], a[href*="facebook"], [class*="share"]');

    if (await socialLinks.count() > 0) {
      // Social links should be visible
      const firstSocial = socialLinks.first();
      await firstSocial.scrollIntoViewIfNeeded();
      await expect(firstSocial).toBeVisible();
    }
  });
});

test.describe('Blog Navigation - Performance', () => {
  test('blog listing loads quickly', async ({ page }) => {
    const startTime = Date.now();

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

    const loadTime = Date.now() - startTime;

    // Should load in under 3 seconds
    expect(loadTime).toBeLessThan(3000);

    // Content should be visible
    const posts = page.locator('article, [class*="post"]');
    expect(await posts.count()).toBeGreaterThan(0);
  });

  test('blog post loads with minimal delay', async ({ page }) => {
    const startTime = Date.now();

    await page.goto('/blog/getting-started-with-astro');
    await page.waitForLoadState('domcontentloaded');

    const loadTime = Date.now() - startTime;

    // Should load in under 3 seconds
    expect(loadTime).toBeLessThan(3000);

    // Content should be visible
    await expect(page.locator('h1')).toBeVisible();
    await expect(page.locator('article, [class*="prose"]')).toBeVisible();
  });

  test('images lazy load efficiently', async ({ page }) => {
    await page.goto('/blog/getting-started-with-astro');

    const images = page.locator('img');
    const imageCount = await images.count();

    if (imageCount > 0) {
      // Check for lazy loading attribute
      const firstImg = images.first();
      const loading = await firstImg.getAttribute('loading');

      // Modern images should use lazy loading
      // (native or via JavaScript)
      expect(['lazy', null].includes(loading)).toBeTruthy();
    }
  });
});

test.describe('Blog Navigation - Edge Cases', () => {
  test('direct URL access to blog post', async ({ page }) => {
    // Simulate user accessing post via bookmark or search result
    await page.goto('/blog/getting-started-with-astro');

    // Page should load correctly
    await expect(page.locator('h1')).toBeVisible();
    await expect(page.locator('article')).toBeVisible();

    // Navigation should work
    await expect(page.locator('header')).toBeVisible();
    await expect(page.locator('footer')).toBeVisible();
  });

  test('non-existent blog post returns 404', async ({ page }) => {
    const response = await page.goto('/blog/this-post-does-not-exist-404');

    // Should return 404 or redirect
    if (response) {
      const status = response.status();
      expect([404, 301, 302].includes(status)).toBeTruthy();
    }
  });

  test('blog listing with no posts', async ({ page }) => {
    await page.goto('/blog');

    // Even with no posts, page should render
    await expect(page.locator('main')).toBeVisible();

    // Should show message or empty state
    const hasContent = await page.locator('article, [class*="post"], [class*="empty"], h1').count() > 0;
    expect(hasContent).toBeTruthy();
  });
});
