/**
 * Behavioral Verification: Content Intelligence Mutation Buttons (R9FE-105)
 *
 * This spec verifies the useMutationButton hook integration for:
 * 1. Freshness page "Re-run analysis" button
 * 2. TopicClusters page "Refresh analysis" button
 *
 * Golden Path (both buttons):
 *   - Button visible when workflow is complete
 *   - Click enters loading state (button disabled, spinner visible)
 *   - POST request fires to correct endpoint
 *   - Request succeeds (200 OK)
 *   - Loading state clears after response
 *   - Zero console errors, zero failed XHRs
 *
 * Sad Path (Freshness only):
 *   - Double-click → second click blocked by double-submit guard
 *   - Only ONE POST request fires
 *
 * Scope: Changed user-facing workflows from R9FE-105 refactoring session.
 */

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

test.describe('Content Intelligence mutation buttons (useMutationButton)', () => {
  let consoleErrors: string[] = [];
  let failedRequests: { status: number; url: string }[] = [];

  test.beforeEach(async ({ page }) => {
    consoleErrors = [];
    failedRequests = [];

    // Capture console errors
    page.on('console', (msg) => {
      if (msg.type() === 'error') {
        consoleErrors.push(msg.text());
      }
    });

    // Capture uncaught exceptions
    page.on('pageerror', (err) => {
      consoleErrors.push(`${err.name}: ${err.message}`);
    });

    // Capture failed XHRs (4xx/5xx)
    page.on('response', (response) => {
      const resourceType = response.request().resourceType();
      if (!response.ok() && (resourceType === 'xhr' || resourceType === 'fetch')) {
        failedRequests.push({
          status: response.status(),
          url: response.url(),
        });
      }
    });
  });

  test('Freshness: re-run button loads and fires POST', async ({ page, seedData }) => {
    // Navigate to Freshness page
    await page.goto(`/sites/${seedData.siteId}/content-intelligence/freshness`, {
      waitUntil: 'domcontentloaded',
    });

    // Verify page title loaded
    await expect(page.locator('text=Find stale pages')).toBeVisible({ timeout: 10_000 });

    // Find "Re-run analysis" button
    const rerunButton = page.locator('button:has-text("Re-run analysis")').first();
    await expect(rerunButton).toBeVisible();

    // Before click: button should not be disabled
    await expect(rerunButton).not.toBeDisabled();

    // Track the POST request
    const responsePromise = page.waitForResponse(
      (resp) =>
        resp.request().method() === 'POST' &&
        resp.url().includes('/freshness') &&
        resp.status() === 200
    );

    // Click button
    await rerunButton.click();

    // After click: button should enter loading state (disabled)
    // LoadingButton disables during loading
    await expect(rerunButton).toBeDisabled({ timeout: 5_000 });

    // Wait for POST to complete
    const response = await responsePromise;
    expect(response.status()).toBe(200);

    // After request: loading state should clear
    // Give Inertia's onFinish callback time to fire (clears processing state)
    await page.waitForTimeout(500);
    await expect(rerunButton).not.toBeDisabled();
  });

  test('Freshness: double-click blocks second submit', async ({ page, seedData }) => {
    await page.goto(`/sites/${seedData.siteId}/content-intelligence/freshness`, {
      waitUntil: 'domcontentloaded',
    });

    const rerunButton = page.locator('button:has-text("Re-run analysis")').first();
    await expect(rerunButton).toBeVisible();

    // Track all POST requests to freshness
    const postRequests: string[] = [];
    page.on('request', (req) => {
      if (req.method() === 'POST' && req.url().includes('/freshness')) {
        postRequests.push(req.url());
      }
    });

    // Double-click: the hook's onClick guard (processingRef.current) blocks the second click
    // before it reaches the router call
    await rerunButton.click();
    await rerunButton.click(); // Immediate second click

    // Wait for the initial request to settle
    await page.waitForTimeout(1500);

    // Only ONE POST should have fired (second click was blocked at onClick)
    const freshnessPosts = postRequests.filter((url) => url.includes('/freshness'));
    expect(freshnessPosts.length).toBe(1);
  });

  test('TopicClusters: refresh button loads and fires POST', async ({ page, seedData }) => {
    // Navigate to TopicClusters page
    await page.goto(`/sites/${seedData.siteId}/content-intelligence/topic-clusters`, {
      waitUntil: 'domcontentloaded',
    });

    // Verify page loaded
    await expect(page.locator('text=Topic Gaps')).toBeVisible({ timeout: 10_000 });

    // Find "Refresh analysis" button
    const refreshButton = page.locator('button:has-text("Refresh analysis")').first();
    await expect(refreshButton).toBeVisible();

    // Before click: not disabled
    await expect(refreshButton).not.toBeDisabled();

    // Track the POST request
    const responsePromise = page.waitForResponse(
      (resp) =>
        resp.request().method() === 'POST' &&
        resp.url().includes('/topic-clusters/recompute') &&
        resp.status() === 200
    );

    // Click button
    await refreshButton.click();

    // After click: enters loading state
    await expect(refreshButton).toBeDisabled({ timeout: 5_000 });

    // Wait for POST to complete
    const response = await responsePromise;
    expect(response.status()).toBe(200);

    // After request: loading clears
    await page.waitForTimeout(500);
    await expect(refreshButton).not.toBeDisabled();
  });

  test('Zero console errors across all tests', () => {
    expect(consoleErrors).toEqual(
      [],
      `Expected no console errors, but found: ${consoleErrors.join('; ')}`
    );
  });

  test('Zero failed XHRs across all tests', () => {
    expect(failedRequests).toEqual(
      [],
      `Expected no failed XHRs, but found: ${failedRequests.map((r) => `${r.status} ${r.url}`).join('; ')}`
    );
  });
});
