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

/**
 * Real-time Attachment Synchronization Tests
 *
 * These tests verify that attachment messages sync correctly across
 * different message paths (WebSocket and REST API).
 *
 * True multi-user testing would require:
 * - Two browser contexts with different user sessions
 * - Or mock WebSocket server
 *
 * Current approach: Simulate WebSocket receipt via Redux dispatch
 */

const TEST_SESSION_ID = process.env.TEST_SESSION_ID || 'test-session-id';

// Helper to access Redux store in test environment
async function getReduxStore(page: Page) {
  return page.evaluate(() => (window as any).__REDUX_STORE__);
}

// Helper to dispatch Redux action
async function dispatchAction(page: Page, action: any) {
  return page.evaluate((actionData) => {
    const store = (window as any).__REDUX_STORE__;
    if (store) {
      store.dispatch(actionData);
    }
  }, action);
}

// Helper to get chat messages from Redux
async function getChatMessages(page: Page, channel: string) {
  return page.evaluate((ch) => {
    const store = (window as any).__REDUX_STORE__;
    if (store) {
      const state = store.getState();
      return state.sessionChat?.messagesByChannel?.[ch] || [];
    }
    return [];
  }, channel);
}

test.describe('Real-time Attachment Synchronization', () => {

  test.describe('WebSocket Message Receipt', () => {

    test('attachment message from WebSocket appears in chat', async ({ page }) => {
      // This test requires being in an active session
      // Skip if not in session context
      test.skip(!process.env.TEST_SESSION_ACTIVE, 'Requires active session');

      const attachmentMessage = {
        type: 'sessionChat/addMessageFromWebSocket',
        payload: {
          id: 'test-msg-123',
          senderId: 'user-456',
          senderName: 'Test User',
          message: '',
          createdAt: new Date().toISOString(),
          channel: 'session',
          sessionId: TEST_SESSION_ID,
          purpose: 'Notation File',
          attachmentId: 'attachment-789',
          attachmentType: 'notation',
          attachmentName: 'test-file.pdf',
          attachmentSize: 1024
        }
      };

      // Dispatch simulated WebSocket message
      await dispatchAction(page, attachmentMessage);

      // Verify message appears in Redux state
      const messages = await getChatMessages(page, TEST_SESSION_ID);
      const found = messages.find((m: any) => m.id === 'test-msg-123');

      expect(found).toBeDefined();
      expect(found.attachmentId).toBe('attachment-789');
      expect(found.attachmentName).toBe('test-file.pdf');
    });

    test('duplicate WebSocket message is deduplicated', async ({ page }) => {
      test.skip(!process.env.TEST_SESSION_ACTIVE, 'Requires active session');

      const messageId = 'dedup-test-' + Date.now();
      const attachmentMessage = {
        type: 'sessionChat/addMessageFromWebSocket',
        payload: {
          id: messageId,
          senderId: 'user-456',
          senderName: 'Test User',
          message: '',
          createdAt: new Date().toISOString(),
          channel: 'session',
          sessionId: TEST_SESSION_ID,
          purpose: 'Audio File',
          attachmentId: 'attachment-dedup',
          attachmentType: 'audio',
          attachmentName: 'test-audio.mp3',
          attachmentSize: 2048
        }
      };

      // Dispatch same message twice (simulates network retry)
      await dispatchAction(page, attachmentMessage);
      await dispatchAction(page, attachmentMessage);

      // Verify message appears only once
      const messages = await getChatMessages(page, TEST_SESSION_ID);
      const matches = messages.filter((m: any) => m.id === messageId);

      expect(matches.length).toBe(1);
    });

  });

  test.describe('Chat History Integration', () => {

    test('WebSocket message and REST API message with same ID deduplicate', async ({ page }) => {
      test.skip(!process.env.TEST_SESSION_ACTIVE, 'Requires active session');

      const sharedMessageId = 'shared-msg-' + Date.now();

      // Simulate message already loaded from REST API
      const restMessage = {
        type: 'sessionChat/addMessageFromWebSocket', // Use same reducer for test
        payload: {
          id: sharedMessageId,
          senderId: 'user-789',
          senderName: 'History User',
          message: '',
          createdAt: new Date(Date.now() - 60000).toISOString(), // 1 min ago
          channel: 'session',
          sessionId: TEST_SESSION_ID,
          purpose: 'Notation File',
          attachmentId: 'att-shared',
          attachmentType: 'notation',
          attachmentName: 'shared-file.pdf',
          attachmentSize: null // REST API doesn't have size
        }
      };

      // Simulate WebSocket message with same ID (different source)
      const wsMessage = {
        type: 'sessionChat/addMessageFromWebSocket',
        payload: {
          ...restMessage.payload,
          attachmentSize: 3072 // WebSocket has size
        }
      };

      // Add REST message first
      await dispatchAction(page, restMessage);

      // Then WebSocket message arrives (should be deduplicated)
      await dispatchAction(page, wsMessage);

      // Verify only one message exists
      const messages = await getChatMessages(page, TEST_SESSION_ID);
      const matches = messages.filter((m: any) => m.id === sharedMessageId);

      expect(matches.length).toBe(1);
      // First message wins (REST), so attachmentSize should be null
      expect(matches[0].attachmentSize).toBeNull();
    });

  });

});

test.describe('Attachment Message Display', () => {

  test('attachment message shows filename and metadata', async ({ page }) => {
    // Navigate to a page with chat window
    test.skip(!process.env.TEST_SESSION_ACTIVE, 'Requires active session');

    // Dispatch test attachment message
    const attachmentMessage = {
      type: 'sessionChat/addMessageFromWebSocket',
      payload: {
        id: 'display-test-' + Date.now(),
        senderId: 'user-display',
        senderName: 'Display Tester',
        message: '',
        createdAt: new Date().toISOString(),
        channel: 'session',
        sessionId: TEST_SESSION_ID,
        purpose: 'Notation File',
        attachmentId: 'att-display',
        attachmentType: 'notation',
        attachmentName: 'my-music-sheet.pdf',
        attachmentSize: 1536000 // ~1.5 MB
      }
    };

    await dispatchAction(page, attachmentMessage);

    // Open chat window if not open
    await page.click('[data-testid="chat-button"]').catch(() => {
      // Button might not exist or chat might be open
    });

    // Look for attachment message in chat
    const attachmentElement = page.locator('text=my-music-sheet.pdf');

    // Note: This test may need adjustment based on actual test environment
    // The key assertion is that the message was dispatched and would render
    const messages = await getChatMessages(page, TEST_SESSION_ID);
    const found = messages.find((m: any) => m.attachmentName === 'my-music-sheet.pdf');
    expect(found).toBeDefined();
  });

});
