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

/**
 * LiveComponents: Real-time Updates Tests
 *
 * Tests SSE (Server-Sent Events) and real-time component updates
 */
test.describe('LiveComponents Real-time Updates', () => {
  test.beforeEach(async ({ page }) => {
    await page.goto('/');
  });

  test('should establish SSE connection (if present)', async ({ page }) => {
    // Listen for EventSource connections
    const sseConnections: string[] = [];

    page.on('request', (request) => {
      if (request.url().includes('/sse') || request.headers()['accept']?.includes('text/event-stream')) {
        sseConnections.push(request.url());
      }
    });

    // Wait for potential SSE connections
    await page.waitForTimeout(2000);

    // If SSE is implemented, we should have connections
    // This is informational - not all pages may have SSE
    console.log('SSE Connections:', sseConnections);
  });

  test('should handle component updates via HTMX', async ({ page }) => {
    // Look for HTMX-enabled elements
    const htmxElements = page.locator('[hx-get], [hx-post], [hx-trigger]');
    const count = await htmxElements.count();

    if (count === 0) {
      test.skip();
      return;
    }

    // Track HTMX requests
    let htmxRequestMade = false;

    page.on('request', (request) => {
      const headers = request.headers();
      if (headers['hx-request'] === 'true') {
        htmxRequestMade = true;
      }
    });

    // Trigger first HTMX element
    const firstElement = htmxElements.first();
    await firstElement.click();

    // Wait for request
    await page.waitForTimeout(1000);

    // HTMX request should have been made
    expect(htmxRequestMade).toBe(true);
  });

  test('should update DOM without full page reload', async ({ page }) => {
    const htmxElements = page.locator('[hx-get], [hx-post]');
    const count = await htmxElements.count();

    if (count === 0) {
      test.skip();
      return;
    }

    // Track page loads
    let pageReloaded = false;
    page.on('load', () => {
      pageReloaded = true;
    });

    // Get initial page state
    const initialUrl = page.url();

    // Trigger HTMX action
    await htmxElements.first().click();
    await page.waitForTimeout(1500);

    // URL should not change (unless it's a navigation)
    const currentUrl = page.url();

    // Page should not have reloaded for simple updates
    // (this is a soft check as some actions might navigate)
    if (currentUrl === initialUrl) {
      expect(pageReloaded).toBe(false);
    }
  });

  test('should handle loading states during updates', async ({ page }) => {
    // Look for loading indicators
    const loadingIndicators = page.locator('[hx-indicator], .htmx-request, [data-loading]');

    // Trigger update if HTMX elements exist
    const htmxElements = page.locator('[hx-get], [hx-post]');
    const count = await htmxElements.count();

    if (count === 0) {
      test.skip();
      return;
    }

    // Trigger action and check for loading state
    await htmxElements.first().click();

    // During request, loading indicator might be visible
    await page.waitForTimeout(100);

    // After request, loading should be hidden
    await page.waitForTimeout(2000);

    const loadingCount = await loadingIndicators.count();
    console.log('Loading indicators found:', loadingCount);
  });

  test('should preserve form data during partial updates', async ({ page }) => {
    const forms = page.locator('form');
    const formCount = await forms.count();

    if (formCount === 0) {
      test.skip();
      return;
    }

    const form = forms.first();
    const inputs = form.locator('input[type="text"], input[type="email"]');
    const inputCount = await inputs.count();

    if (inputCount === 0) {
      test.skip();
      return;
    }

    // Fill some data
    const testValue = 'test-value-123';
    await inputs.first().fill(testValue);

    // Wait a bit
    await page.waitForTimeout(500);

    // Value should still be present
    const currentValue = await inputs.first().inputValue();
    expect(currentValue).toBe(testValue);
  });

  test('should handle WebSocket connections (if present)', async ({ page }) => {
    // Track WebSocket connections
    const wsConnections: string[] = [];

    page.on('websocket', (ws) => {
      wsConnections.push(ws.url());

      ws.on('framesent', (event) => {
        console.log('WebSocket sent:', event.payload);
      });

      ws.on('framereceived', (event) => {
        console.log('WebSocket received:', event.payload);
      });
    });

    // Wait for potential WebSocket connections
    await page.waitForTimeout(2000);

    // Log WebSocket connections (informational)
    console.log('WebSocket Connections:', wsConnections);

    // If WebSocket is used, we should have connections
    if (wsConnections.length > 0) {
      expect(wsConnections.length).toBeGreaterThan(0);
    }
  });

  test('should handle connection errors gracefully', async ({ page }) => {
    // Monitor console errors
    const errors: string[] = [];

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

    // Navigate and wait
    await page.goto('/');
    await page.waitForTimeout(3000);

    // Filter out known/expected errors
    const criticalErrors = errors.filter(
      (error) => !error.includes('favicon') && !error.includes('DevTools')
    );

    // Should not have critical JavaScript errors
    expect(criticalErrors.length).toBe(0);
  });
});
