/**
 * Journey: Action Queue routing + nav/breadcrumb label verification
 *
 * Verifies the browser-observable changes from the "Make Action Queue the
 * primary user destination" workflow (session b941beb4-beec-40a1-a542-d120023284da).
 *
 * Covers SC-7 (verify_by: both):
 *   - Nav sidebar label for `opportunity-map` route reads "Action Queue",
 *     not the legacy "Opportunity Map"
 *   - Breadcrumb on the opportunity-map page reads "Action Queue"
 *
 * Also exercises the changed UI files:
 *   - Pipeline/Index.tsx — page loads without JS errors; empty state renders
 *   - ContentBriefs/Index.tsx — page loads without JS errors; empty state renders
 *   - RecommendationsFirstVisitTour — recommendations page loads without JS errors
 *
 * human_success_check: A solo blogger finishing onboarding lands directly on
 * the Action Queue (their primary work surface), and a viewer-only collaborator
 * cannot trigger paid AI generation — they get a clean 403.
 *
 * The 403-gate (SC-3/SC-4) is verify_by:test and enforced by feature tests.
 * This spec covers only the browser-verifiable portion (SC-7 + UI smoke tests).
 *
 * Scope source: SUCCESS_CRITERIA_b941beb4-beec-40a1-a542-d120023284da.md
 */

import { expect, test } from '../fixtures/auth';

test.describe('SC-7: Action Queue nav + breadcrumb labels', () => {
  test('sidebar nav shows "Action Queue" for the opportunity-map route', async ({
    page,
    seedData,
  }) => {
    const consoleErrors: string[] = [];
    page.on('pageerror', (err) => consoleErrors.push(err.message));
    page.on('console', (msg) => {
      if (msg.type() === 'error') consoleErrors.push(msg.text());
    });

    // Navigate to opportunity-map page
    await page.goto(`/sites/${seedData.siteId}/opportunity-map`, {
      waitUntil: 'domcontentloaded',
    });

    // SC-7: sidebar nav item for this route must show "Action Queue"
    // The SidebarSiteNavV2 renders items from getHubNavStructure (R6IA-001: single canonical source).
    // getHubNavStructure sets label: 'Action Queue' for key: 'opportunity-map'.
    const navActionQueue = page.getByRole('link', { name: /action queue/i }).first();
    await expect(navActionQueue).toBeVisible({ timeout: 10_000 });

    // Ensure NO nav item says "Opportunity Map" (legacy label must be gone).
    // The side-nav label, breadcrumb, and the cross-page CTAs (Pipeline,
    // Content Briefs) were all renamed to "Action Queue" this session — this
    // assertion specifically guards the side-nav label.
    const sideNavItems = page.locator('nav').getByRole('link', { name: /opportunity map/i });
    await expect(sideNavItems).toHaveCount(0);

    // No uncaught JS errors
    const appErrors = consoleErrors.filter(
      (e) =>
        !e.includes('extension') &&
        !e.includes('chrome-extension') &&
        !e.includes('Failed to load resource'),
    );
    expect(appErrors, `Console errors: ${appErrors.join(', ')}`).toHaveLength(0);
  });

  test('breadcrumb on opportunity-map page reads "Action Queue"', async ({ page, seedData }) => {
    await page.goto(`/sites/${seedData.siteId}/opportunity-map`, {
      waitUntil: 'domcontentloaded',
    });

    // SiteBreadcrumb maps 'opportunity-map' → 'Action Queue' via SEGMENT_LABELS.
    // The breadcrumb component renders as aria-current="page" for the last crumb.
    const breadcrumb = page.locator('[aria-current="page"], nav[aria-label="breadcrumb"] *').filter({
      hasText: /action queue/i,
    });

    // Fallback: any text node anywhere on the page with the breadcrumb value.
    // Assert the page shows the label first, then confirm the breadcrumb crumb
    // itself carries it (the primary, precise locator).
    const breadcrumbText = page.getByText(/action queue/i).first();
    await expect(breadcrumbText).toBeVisible({ timeout: 10_000 });
    await expect(breadcrumb.first()).toBeVisible();
  });

  test('opportunity-map page loads without console errors', async ({ page, seedData }) => {
    const errors: string[] = [];
    const failedRequests: string[] = [];
    page.on('pageerror', (err) => errors.push(err.message));
    page.on('console', (msg) => {
      if (msg.type() === 'error') errors.push(msg.text());
    });
    page.on('requestfailed', (req) => failedRequests.push(`${req.method()} ${req.url()}`));
    page.on('response', (res) => {
      if (res.status() >= 400 && !res.url().includes('/api/') && res.url().includes(String(seedData.siteId))) {
        failedRequests.push(`${res.status()} ${res.url()}`);
      }
    });

    await page.goto(`/sites/${seedData.siteId}/opportunity-map`, {
      waitUntil: 'domcontentloaded',
    });

    const appErrors = errors.filter(
      (e) =>
        !e.includes('extension') &&
        !e.includes('chrome-extension') &&
        !e.includes('Failed to load resource'),
    );
    expect(appErrors, `Console errors: ${appErrors.join(', ')}`).toHaveLength(0);
    expect(failedRequests, `Failed requests: ${failedRequests.join(', ')}`).toHaveLength(0);
  });
});

test.describe('Pipeline/Index.tsx — smoke test', () => {
  test('pipeline page loads without JS errors', async ({ page, seedData }) => {
    const errors: string[] = [];
    page.on('pageerror', (err) => errors.push(err.message));
    page.on('console', (msg) => {
      if (msg.type() === 'error') errors.push(msg.text());
    });

    await page.goto(`/sites/${seedData.siteId}/pipeline`, { waitUntil: 'domcontentloaded' });
    await expect(page).toHaveURL(new RegExp(`/sites/${seedData.siteId}/pipeline`));

    const appErrors = errors.filter(
      (e) =>
        !e.includes('extension') &&
        !e.includes('chrome-extension') &&
        !e.includes('Failed to load resource'),
    );
    expect(appErrors, `Console errors: ${appErrors.join(', ')}`).toHaveLength(0);
  });

  test('pipeline page renders heading "Content Pipeline"', async ({ page, seedData }) => {
    await page.goto(`/sites/${seedData.siteId}/pipeline`, { waitUntil: 'domcontentloaded' });

    await expect(page.getByRole('heading', { name: /content pipeline/i })).toBeVisible({
      timeout: 10_000,
    });
  });

  test('pipeline empty state: shows call-to-action when no items', async ({ page, seedData }) => {
    await page.goto(`/sites/${seedData.siteId}/pipeline`, { waitUntil: 'domcontentloaded' });

    // Either renders a kanban board (with items) or an empty state.
    // The page must not be blank or crash — body has meaningful content.
    const bodyText = await page.innerText('body');
    expect(bodyText.trim().length).toBeGreaterThan(50);
  });
});

test.describe('ContentBriefs/Index.tsx — smoke test', () => {
  test('content briefs page loads without JS errors', async ({ page, seedData }) => {
    const errors: string[] = [];
    page.on('pageerror', (err) => errors.push(err.message));
    page.on('console', (msg) => {
      if (msg.type() === 'error') errors.push(msg.text());
    });

    await page.goto(`/sites/${seedData.siteId}/content-briefs`, { waitUntil: 'domcontentloaded' });
    await expect(page).toHaveURL(new RegExp(`/sites/${seedData.siteId}/content-briefs`));

    const appErrors = errors.filter(
      (e) =>
        !e.includes('extension') &&
        !e.includes('chrome-extension') &&
        !e.includes('Failed to load resource'),
    );
    expect(appErrors, `Console errors: ${appErrors.join(', ')}`).toHaveLength(0);
  });

  test('content briefs page renders heading "Content Briefs"', async ({ page, seedData }) => {
    await page.goto(`/sites/${seedData.siteId}/content-briefs`, { waitUntil: 'domcontentloaded' });

    await expect(page.getByRole('heading', { name: /content briefs/i })).toBeVisible({
      timeout: 10_000,
    });
  });
});

test.describe('RecommendationsFirstVisitTour — smoke test', () => {
  test('recommendations page loads without JS errors', async ({ page, seedData }) => {
    const errors: string[] = [];
    page.on('pageerror', (err) => errors.push(err.message));
    page.on('console', (msg) => {
      if (msg.type() === 'error') errors.push(msg.text());
    });

    await page.goto(`/sites/${seedData.siteId}/recommendations`, {
      waitUntil: 'domcontentloaded',
    });
    await expect(page).toHaveURL(new RegExp(`/sites/${seedData.siteId}/recommendations`));

    const appErrors = errors.filter(
      (e) =>
        !e.includes('extension') &&
        !e.includes('chrome-extension') &&
        !e.includes('Failed to load resource'),
    );
    expect(appErrors, `Console errors: ${appErrors.join(', ')}`).toHaveLength(0);
  });
});

test.describe('Permission: unauthenticated access is blocked', () => {
  test('unauthenticated user is redirected from opportunity-map', async ({
    browser,
    seedData,
  }) => {
    const context = await browser.newContext({ storageState: { cookies: [], origins: [] } });
    const page = await context.newPage();

    await page.goto(`/sites/${seedData.siteId}/opportunity-map`);
    await expect(page).toHaveURL(/\/login/);

    await context.close();
  });

  test('unauthenticated user is redirected from pipeline', async ({ browser, seedData }) => {
    const context = await browser.newContext({ storageState: { cookies: [], origins: [] } });
    const page = await context.newPage();

    await page.goto(`/sites/${seedData.siteId}/pipeline`);
    await expect(page).toHaveURL(/\/login/);

    await context.close();
  });
});
