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

test.describe('Restaurant General — smoke tests', () => {
  test('home page loads with restaurant name', async ({ page }) => {
    await page.goto('/');
    await expect(page).toHaveTitle(/The Cedar & Rye/i);
    // Use heading role + level to avoid strict-mode collision (name in nav + hero + footer)
    await expect(page.getByRole('heading', { level: 1 })).toContainText('Cedar');
  });

  test('navigation links are present', async ({ page }) => {
    await page.goto('/');
    const nav = page.getByRole('navigation', { name: 'Main navigation' });
    await expect(nav.getByRole('link', { name: /Menu/i })).toBeVisible();
    await expect(nav.getByRole('link', { name: /Hours/i })).toBeVisible();
    await expect(nav.getByRole('link', { name: /Location/i })).toBeVisible();
    await expect(nav.getByRole('link', { name: /Reserve/i })).toBeVisible();
  });

  test('menu tabs are present and switchable', async ({ page }) => {
    await page.goto('/');
    // Check all 4 menu tabs exist
    await expect(page.getByRole('tab', { name: 'Starters' })).toBeVisible();
    await expect(page.getByRole('tab', { name: 'Mains' })).toBeVisible();
    await expect(page.getByRole('tab', { name: 'Desserts' })).toBeVisible();
    await expect(page.getByRole('tab', { name: 'Drinks' })).toBeVisible();

    // Default panel shows starters content
    await expect(page.getByRole('tabpanel', { name: 'Starters' })).toBeVisible();
    await expect(page.getByRole('tabpanel', { name: 'Starters' }).getByText('Grilled Octopus')).toBeVisible();

    // Click Mains tab
    await page.getByRole('tab', { name: 'Mains' }).click();
    await expect(page.getByRole('tabpanel', { name: 'Mains' })).toBeVisible();
    await expect(page.getByRole('tabpanel', { name: 'Mains' }).getByText('Pan-Seared Duck Breast')).toBeVisible();
  });

  test('hours section shows closed on Monday', async ({ page }) => {
    await page.goto('/');
    // Scope to the hours section to avoid collisions
    const hoursSection = page.locator('#hours');
    await expect(hoursSection.getByRole('heading', { name: 'Hours' })).toBeVisible();
    await expect(hoursSection.getByText('Monday')).toBeVisible();
    await expect(hoursSection.getByText('Closed')).toBeVisible();
  });

  test('hours table shows Saturday brunch note', async ({ page }) => {
    await page.goto('/');
    const hoursSection = page.locator('#hours');
    // Both Sat and Sun show "Brunch + Dinner" — use .first() to avoid strict-mode collision
    await expect(hoursSection.getByText('Brunch + Dinner').first()).toBeVisible();
  });

  test('reservations section has OpenTable link', async ({ page }) => {
    await page.goto('/');
    const reservationsSection = page.locator('#reservations');
    await expect(reservationsSection.getByRole('heading', { name: 'Reservations' })).toBeVisible();
    await expect(reservationsSection.getByRole('link', { name: /Reserve on OpenTable/i })).toBeVisible();
  });

  test('press section has pull quotes', async ({ page }) => {
    await page.goto('/');
    const pressSection = page.locator('#press');
    await expect(pressSection.getByRole('heading', { name: 'Press & Awards' })).toBeVisible();
    await expect(pressSection.getByText('New York Times Dining')).toBeVisible();
    await expect(pressSection.getByText('Eater NY').first()).toBeVisible();
  });

  test('awards section shows Bib Gourmand', async ({ page }) => {
    await page.goto('/');
    await expect(page.getByText('Bib Gourmand')).toBeVisible();
  });

  test('location section shows address', async ({ page }) => {
    await page.goto('/');
    const locationSection = page.locator('#location');
    await expect(locationSection.getByRole('heading', { name: 'Location & Getting Here' })).toBeVisible();
    // Address appears in both the <address> element and the SVG map label — scope to the address element
    await expect(locationSection.locator('address')).toContainText('142 Metropolitan Avenue');
    await expect(locationSection.locator('address')).toContainText('Williamsburg');
  });

  test('newsletter form is present', async ({ page }) => {
    await page.goto('/');
    const form = page.getByRole('form', { name: /Newsletter signup form/i });
    await expect(form).toBeVisible();
    await expect(form.getByLabel(/Email address/i)).toBeVisible();
  });

  test('JSON-LD Restaurant schema is present', async ({ page }) => {
    await page.goto('/');
    const scripts = await page.locator('script[type="application/ld+json"]').all();
    let hasRestaurant = false;
    let hasOpeningHours = false;
    let hasRating = false;
    for (const script of scripts) {
      const content = await script.textContent();
      if (content && content.includes('"Restaurant"')) hasRestaurant = true;
      if (content && content.includes('openingHoursSpecification')) hasOpeningHours = true;
      if (content && content.includes('AggregateRating')) hasRating = true;
    }
    expect(hasRestaurant).toBe(true);
    expect(hasOpeningHours).toBe(true);
    expect(hasRating).toBe(true);
  });

  test('JSON-LD has servesCuisine and acceptsReservations', async ({ page }) => {
    await page.goto('/');
    const scripts = await page.locator('script[type="application/ld+json"]').all();
    let hasCuisine = false;
    let hasReservations = false;
    for (const script of scripts) {
      const content = await script.textContent();
      if (content && content.includes('servesCuisine')) hasCuisine = true;
      if (content && content.includes('acceptsReservations')) hasReservations = true;
    }
    expect(hasCuisine).toBe(true);
    expect(hasReservations).toBe(true);
  });

  test('JSON-LD has no Event type (restaurant, not event venue)', async ({ page }) => {
    await page.goto('/');
    const scripts = await page.locator('script[type="application/ld+json"]').all();
    for (const script of scripts) {
      const content = await script.textContent();
      if (content) {
        // Should not have Event type — that's for Day 20 (conference) and Day 21 (wedding)
        const parsed = JSON.parse(content);
        const graph = parsed['@graph'] || [parsed];
        graph.forEach((node: Record<string, unknown>) => {
          expect(node['@type']).not.toBe('Event');
        });
      }
    }
  });

  test('no github.com deep-links in page source', async ({ page }) => {
    await page.goto('/');
    const html = await page.content();
    const deepLinks = html.match(/github\.com\/allanninal\/templates[^"'\s]*/g);
    expect(deepLinks).toBeNull();
  });

  test('chef name appears in about section', async ({ page }) => {
    await page.goto('/');
    const aboutSection = page.locator('#about');
    // Chef name appears in bio paragraph, blockquote footer, and SVG — use the blockquote footer
    await expect(aboutSection.locator('blockquote footer')).toContainText('Marcus Webb');
  });

  test('private events section shows inquiry link', async ({ page }) => {
    await page.goto('/');
    const eventsSection = page.locator('#events');
    await expect(eventsSection.getByRole('heading', { name: /Private Events/i })).toBeVisible();
    await expect(eventsSection.getByRole('link', { name: /Inquire About Events/i })).toBeVisible();
  });
});
