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

/**
 * Error Page Workflow Verification
 *
 * Tests that the static Inertia Error page (resources/js/Pages/Error.tsx)
 * renders correctly for exception conditions (404, 403, 500) during web
 * navigation (Inertia requests with X-Inertia header).
 */

test('Error page renders 404 for non-existent route', async ({ page }) => {
  // Collect console messages to verify no uncaught errors
  const consoleLogs: string[] = [];
  const consoleErrors: string[] = [];

  page.on('console', (msg) => {
    consoleLogs.push(`[${msg.type()}] ${msg.text()}`);
    if (msg.type() === 'error') {
      consoleErrors.push(msg.text());
    }
  });

  // First, load the root page to establish an Inertia context
  // (so subsequent requests will automatically include X-Inertia header)
  await page.goto('/');
  await page.waitForLoadState('networkidle');

  // Now request a non-existent route with explicit X-Inertia header
  const response = await page.request.get('/nonexistent-route-404', {
    headers: {
      'X-Inertia': 'true',
    },
  });

  // Verify response status is 404
  expect(response.status()).toBe(404);

  // Verify the response is an Inertia JSON page
  const responseBody = await response.text();
  expect(responseBody).toContain('"component":"Error"');
  expect(responseBody).toContain('"status":404');
  const body = JSON.parse(responseBody);
  expect(body.props.status).toBe(404);

  console.log('404 Test passed - Error component returned for non-existent route');
  console.log('Console logs:', consoleLogs);
  console.log('Console errors:', consoleErrors);

  // Verify no uncaught console errors occurred
  expect(consoleErrors).toEqual(
    [],
    `Uncaught console errors: ${consoleErrors.join(', ')}`
  );
});

test('Error page honors 404-oracle for authorization failures', async ({ page }) => {
  // SitePolicy uses denyWithStatus(404) for the "404-oracle" pattern:
  // outsiders cannot distinguish "site exists but not yours" from "no such site".
  // The exception handler must preserve this attached status, not map it to 403.

  const consoleLogs: string[] = [];
  const consoleErrors: string[] = [];

  page.on('console', (msg) => {
    consoleLogs.push(`[${msg.type()}] ${msg.text()}`);
    if (msg.type() === 'error') {
      consoleErrors.push(msg.text());
    }
  });

  // POST to the test oracle route with Inertia header
  const response = await page.request.post('/test-web-oracle-404', {
    headers: {
      'X-Inertia': 'true',
    },
  });

  // Verify 404 status (not 403)
  expect(response.status()).toBe(404);

  // Verify Inertia JSON response
  const body = await response.json();
  expect(body.component).toBe('Error');
  expect(body.props.status).toBe(404);

  // Verify the JSON response structure matches Inertia format
  expect(body.url).toBeDefined();
  expect(body.version).toBeDefined();

  console.log('Oracle test response:', JSON.stringify(body, null, 2));
  console.log('Oracle test console logs:', consoleLogs);
  console.log('Oracle test console errors:', consoleErrors);

  // Verify no uncaught console errors
  expect(consoleErrors).toEqual(
    [],
    `Uncaught console errors: ${consoleErrors.join(', ')}`
  );
});

test('Error page "Go home" button navigates to root', async ({ page }) => {
  const consoleLogs: string[] = [];

  page.on('console', (msg) => {
    consoleLogs.push(`[${msg.type()}] ${msg.text()}`);
  });

  // Load the root page first to establish an Inertia context
  await page.goto('/');
  await page.waitForLoadState('networkidle');

  // Now navigate via Inertia link (which adds X-Inertia header automatically)
  // to a 404 error page
  await page.request.get('/nonexistent-button-test', {
    headers: {
      'X-Inertia': 'true',
    },
  });

  // Simulate loading the Error page by fetching with Inertia header
  const errorResponse = await page.request.get('/nonexistent-button-test', {
    headers: {
      'X-Inertia': 'true',
    },
  });

  expect(errorResponse.status()).toBe(404);
  const body = await errorResponse.json();
  expect(body.component).toBe('Error');

  // The "Go home" button should link to "/" (root)
  expect(body.props.status).toBe(404);

  console.log('Button test console logs:', consoleLogs);
  console.log('Button test passed - Error page with 404 status verified');
});
