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

// ── Hero ───────────────────────────────────────────────────────────────

test('hero shows newsletter tagline', async ({ page }) => {
  await page.goto('/');
  await expect(page.locator('h1')).toContainText(/weekly letter/i);
  await expect(page.locator('h1')).toContainText(/book history/i);
});

test('hero eyebrow shows cadence + founding year', async ({ page }) => {
  await page.goto('/');
  const eyebrow = page.locator('p.label-eyebrow').first();
  await expect(eyebrow).toContainText(/every sunday/i);
  await expect(eyebrow).toContainText('2022');
});

test('subscriber + unsubscribe trust line is visible in hero', async ({ page }) => {
  await page.goto('/');
  await expect(page.getByText(/4,200/).first()).toBeVisible();
  await expect(page.getByText(/unsubscribe in one click/i).first()).toBeVisible();
});

// ── Subscribe form (Buttondown by default) ────────────────────────────

test('hero subscribe form posts to Buttondown action', async ({ page }) => {
  await page.goto('/');
  const form = page.locator('form#subscribe-hero');
  await expect(form).toBeVisible();
  expect(await form.getAttribute('method')).toBe('post');
  expect(await form.getAttribute('action')).toContain('buttondown.email');
  expect(await form.getAttribute('data-provider')).toBe('buttondown');
});

test('subscribe form has email input with autocomplete + required', async ({ page }) => {
  await page.goto('/');
  const email = page.locator('form#subscribe-hero input[type="email"]');
  await expect(email).toBeVisible();
  expect(await email.getAttribute('autocomplete')).toBe('email');
  expect(await email.getAttribute('name')).toBe('email');
  expect(await email.getAttribute('required')).not.toBeNull();
});

test('email input is keyboard-fillable and has accessible label', async ({ page }) => {
  await page.goto('/');
  const email = page.locator('form#subscribe-hero input[type="email"]');
  await email.fill('reader@example.com');
  expect(await email.inputValue()).toBe('reader@example.com');
  // Accessible name comes from sr-only <label> + aria-label
  const ariaLabel = await email.getAttribute('aria-label');
  expect(ariaLabel).toBeTruthy();
  expect(ariaLabel!.length).toBeGreaterThan(3);
});

test('two subscribe forms render (hero + final)', async ({ page }) => {
  await page.goto('/');
  await expect(page.locator('form#subscribe-hero')).toBeVisible();
  await expect(page.locator('form#subscribe-final')).toBeVisible();
});

// ── What you get — three-item value prop ──────────────────────────────

test('what-you-get section renders three items with eyebrows', async ({ page }) => {
  await page.goto('/');
  const items = page.locator('section[aria-labelledby="what-heading"] ul[role="list"] > li');
  expect(await items.count()).toBe(3);
  for (const eyebrow of ['Topics', 'Format', 'Cadence']) {
    await expect(page.locator('section[aria-labelledby="what-heading"]').getByText(eyebrow, { exact: true })).toBeVisible();
  }
});

// ── Sample issues ────────────────────────────────────────────────────

test('sample issues renders four cards', async ({ page }) => {
  await page.goto('/');
  const cards = page.locator('section#issues ul[role="list"] > li');
  expect(await cards.count()).toBe(4);
});

test('each issue card links to the public archive permalink', async ({ page }) => {
  await page.goto('/');
  const links = page.locator('section#issues a.issue-card');
  expect(await links.count()).toBe(4);
  for (let i = 0; i < 4; i++) {
    const href = await links.nth(i).getAttribute('href');
    expect(href, `issue card ${i} should link to archive`).toMatch(/^https?:\/\//);
    expect(await links.nth(i).getAttribute('target')).toBe('_blank');
    expect(await links.nth(i).getAttribute('rel')).toContain('noopener');
  }
});

test('issue cards show date as ISO datetime + human-formatted time', async ({ page }) => {
  await page.goto('/');
  const times = page.locator('section#issues time');
  expect(await times.count()).toBe(4);
  // First (most recent) date is 2026-04-26
  expect(await times.first().getAttribute('datetime')).toBe('2026-04-26');
  await expect(times.first()).toContainText(/april/i);
});

test('issue cards show read-time meta', async ({ page }) => {
  await page.goto('/');
  const card = page.locator('section#issues a.issue-card').first();
  await expect(card).toContainText(/min read/i);
});

// ── Issue counter band ──────────────────────────────────────────────

test('issue counter band shows issues + cadence + read time', async ({ page }) => {
  await page.goto('/');
  const band = page.locator('section[aria-labelledby="counter-heading"]');
  await expect(band).toBeVisible();
  await expect(band.getByText(/84/).first()).toBeVisible();
  await expect(band.getByText(/issues/i).first()).toBeVisible();
  await expect(band.getByText(/every sunday/i).first()).toBeVisible();
  await expect(band.getByText(/min read/i).first()).toBeVisible();
});

// ── Author / About ──────────────────────────────────────────────────

test('about section shows author name + bio + monogram avatar', async ({ page }) => {
  await page.goto('/');
  const about = page.locator('section#about');
  await expect(about).toBeVisible();
  await expect(about.getByText('Allan Ninal').first()).toBeVisible();
  // Monogram avatar (first 2 initials)
  await expect(about.locator('.avatar-monogram').first()).toBeVisible();
});

test('about section has no <img> tags (uses CSS-only monogram)', async ({ page }) => {
  await page.goto('/');
  const imgs = page.locator('section#about img');
  expect(await imgs.count()).toBe(0);
});

// ── Reader quotes ───────────────────────────────────────────────────

test('reader quotes section shows three pull quotes', async ({ page }) => {
  await page.goto('/');
  const quotes = page.locator('section[aria-labelledby="quotes-heading"] blockquote');
  expect(await quotes.count()).toBe(3);
});

test('reader quotes each have an attribution', async ({ page }) => {
  await page.goto('/');
  const cites = page.locator('section[aria-labelledby="quotes-heading"] cite');
  expect(await cites.count()).toBe(3);
  for (let i = 0; i < 3; i++) {
    const text = await cites.nth(i).textContent();
    expect(text!.trim().length).toBeGreaterThan(2);
  }
});

// ── Final CTA ──────────────────────────────────────────────────────

test('final CTA section has subscribe form + "read archive" link', async ({ page }) => {
  await page.goto('/');
  const cta = page.locator('section[aria-labelledby="final-cta-heading"]');
  await expect(cta).toBeVisible();
  await expect(cta.locator('form#subscribe-final')).toBeVisible();
  await expect(cta.getByRole('link', { name: /read the archive first/i })).toBeVisible();
});

// ── Header subscribe button ───────────────────────────────────────

test('header has Subscribe CTA pointing to #subscribe', async ({ page }) => {
  await page.goto('/');
  const subBtn = page.locator('header').getByRole('link', { name: /^subscribe$/i });
  await expect(subBtn).toBeVisible();
  expect(await subBtn.getAttribute('href')).toBe('#subscribe');
});

// ── External-link safety ──────────────────────────────────────────

test('all target=_blank links use rel="noopener noreferrer"', async ({ page }) => {
  await page.goto('/');
  const ext = await page.locator('a[target="_blank"]').all();
  const unsafe: string[] = [];
  for (const a of ext) {
    const rel = await a.getAttribute('rel');
    const href = await a.getAttribute('href');
    if (!rel || !rel.includes('noopener') || !rel.includes('noreferrer')) {
      unsafe.push(`${href} — rel="${rel}"`);
    }
  }
  expect(unsafe).toEqual([]);
});

// ── LinkedIn-primary in footer ───────────────────────────────────

test('footer LinkedIn link uses oxblood accent color', async ({ page }) => {
  await page.goto('/');
  const li = page.locator('footer a[href*="linkedin.com"]').first();
  const color = await li.evaluate((el) => getComputedStyle(el).color);
  // accent #881337 → rgb(136, 19, 55)
  expect(color).toBe('rgb(136, 19, 55)');
});

// ── Light-only theme — no dark scheme override ───────────────────

test('color-scheme meta declares light only', async ({ page }) => {
  await page.goto('/');
  const meta = await page.locator('meta[name="color-scheme"]').getAttribute('content');
  expect(meta).toBe('light');
});
