/**
 * Tests for CHAT_MESSAGE WebSocket handler in useSessionWebSocket
 * Tests message transformation from Protocol Buffer format to Redux format
 * and unread count increment logic based on window state
 */

// Import the helper function for testing
import { addMessageFromWebSocket, incrementUnreadCount } from '../../store/features/sessionChatSlice';

// Mock the helper function that's exported from the hook file
const getChannelKeyFromMessage = (message) => {
  if (message.channel === 'session' && message.session_id) {
    return message.session_id;
  }
  if (message.channel === 'lesson' && message.lesson_session_id) {
    return message.lesson_session_id;
  }
  return 'global';
};

describe('useSessionWebSocket - CHAT_MESSAGE handler', () => {
  describe('message transformation', () => {
    test('should transform session channel message correctly', () => {
      // Protocol Buffer format from WebSocket
      const protobufMessage = {
        type: 'CHAT_MESSAGE',
        msg_id: 'msg-1',
        user_id: 'user-1',
        user_name: 'John Doe',
        message: 'Hello world',
        channel: 'session',
        session_id: 'session-abc',
        created_at: '2026-01-26T12:00:00Z'
      };

      // Transform using the same logic as the handler
      const transformedMessage = {
        id: protobufMessage.msg_id,
        senderId: protobufMessage.user_id,
        senderName: protobufMessage.user_name,
        message: protobufMessage.message,
        channel: protobufMessage.channel,
        sessionId: protobufMessage.session_id || null,
        lessonSessionId: protobufMessage.lesson_session_id || null,
        createdAt: protobufMessage.created_at,
        purpose: protobufMessage.purpose || null,
        musicNotation: protobufMessage.music_notation || null,
        claimedRecording: protobufMessage.claimed_recording || null
      };

      // Expected Redux format after transformation
      const expectedReduxFormat = {
        id: 'msg-1',
        senderId: 'user-1',
        senderName: 'John Doe',
        message: 'Hello world',
        channel: 'session',
        sessionId: 'session-abc',
        lessonSessionId: null,
        createdAt: '2026-01-26T12:00:00Z',
        purpose: null,
        musicNotation: null,
        claimedRecording: null
      };

      expect(transformedMessage).toEqual(expectedReduxFormat);
    });

    test('should transform global channel message correctly', () => {
      const protobufMessage = {
        type: 'CHAT_MESSAGE',
        msg_id: 'msg-2',
        user_id: 'user-2',
        user_name: 'Jane Smith',
        message: 'Global message',
        channel: 'global',
        created_at: '2026-01-26T12:01:00Z'
      };

      const transformedMessage = {
        id: protobufMessage.msg_id,
        senderId: protobufMessage.user_id,
        senderName: protobufMessage.user_name,
        message: protobufMessage.message,
        channel: protobufMessage.channel,
        sessionId: protobufMessage.session_id || null,
        lessonSessionId: protobufMessage.lesson_session_id || null,
        createdAt: protobufMessage.created_at,
        purpose: protobufMessage.purpose || null,
        musicNotation: protobufMessage.music_notation || null,
        claimedRecording: protobufMessage.claimed_recording || null
      };

      const expectedReduxFormat = {
        id: 'msg-2',
        senderId: 'user-2',
        senderName: 'Jane Smith',
        message: 'Global message',
        channel: 'global',
        sessionId: null,
        lessonSessionId: null,
        createdAt: '2026-01-26T12:01:00Z',
        purpose: null,
        musicNotation: null,
        claimedRecording: null
      };

      expect(transformedMessage).toEqual(expectedReduxFormat);
    });

    test('should transform lesson channel message correctly', () => {
      const protobufMessage = {
        type: 'CHAT_MESSAGE',
        msg_id: 'msg-3',
        user_id: 'user-3',
        user_name: 'Teacher',
        message: 'Lesson feedback',
        channel: 'lesson',
        lesson_session_id: 'lesson-123',
        created_at: '2026-01-26T12:02:00Z'
      };

      const transformedMessage = {
        id: protobufMessage.msg_id,
        senderId: protobufMessage.user_id,
        senderName: protobufMessage.user_name,
        message: protobufMessage.message,
        channel: protobufMessage.channel,
        sessionId: protobufMessage.session_id || null,
        lessonSessionId: protobufMessage.lesson_session_id || null,
        createdAt: protobufMessage.created_at,
        purpose: protobufMessage.purpose || null,
        musicNotation: protobufMessage.music_notation || null,
        claimedRecording: protobufMessage.claimed_recording || null
      };

      const expectedReduxFormat = {
        id: 'msg-3',
        senderId: 'user-3',
        senderName: 'Teacher',
        message: 'Lesson feedback',
        channel: 'lesson',
        sessionId: null,
        lessonSessionId: 'lesson-123',
        createdAt: '2026-01-26T12:02:00Z',
        purpose: null,
        musicNotation: null,
        claimedRecording: null
      };

      expect(transformedMessage).toEqual(expectedReduxFormat);
    });

    test('should transform all optional Protocol Buffer fields', () => {
      const protobufMessage = {
        type: 'CHAT_MESSAGE',
        msg_id: 'msg-4',
        user_id: 'user-4',
        user_name: 'Musician',
        message: 'Recording annotation',
        channel: 'session',
        session_id: 'session-xyz',
        created_at: '2026-01-26T12:03:00Z',
        purpose: 'feedback',
        music_notation: 'C major scale',
        claimed_recording: 'recording-456'
      };

      const transformedMessage = {
        id: protobufMessage.msg_id,
        senderId: protobufMessage.user_id,
        senderName: protobufMessage.user_name,
        message: protobufMessage.message,
        channel: protobufMessage.channel,
        sessionId: protobufMessage.session_id || null,
        lessonSessionId: protobufMessage.lesson_session_id || null,
        createdAt: protobufMessage.created_at,
        purpose: protobufMessage.purpose || null,
        musicNotation: protobufMessage.music_notation || null,
        claimedRecording: protobufMessage.claimed_recording || null
      };

      const expectedReduxFormat = {
        id: 'msg-4',
        senderId: 'user-4',
        senderName: 'Musician',
        message: 'Recording annotation',
        channel: 'session',
        sessionId: 'session-xyz',
        lessonSessionId: null,
        createdAt: '2026-01-26T12:03:00Z',
        purpose: 'feedback',
        musicNotation: 'C major scale',
        claimedRecording: 'recording-456'
      };

      expect(transformedMessage).toEqual(expectedReduxFormat);
    });
  });

  describe('channel key construction', () => {
    test('should construct channel key for session messages', () => {
      // Session messages: channel key = sessionId directly
      const sessionMessage = {
        type: 'CHAT_MESSAGE',
        channel: 'session',
        session_id: 'session-abc'
      };

      const channelKey = getChannelKeyFromMessage(sessionMessage);
      expect(channelKey).toBe('session-abc');
    });

    test('should construct channel key for lesson messages', () => {
      // Lesson messages: channel key = lessonSessionId directly
      const lessonMessage = {
        type: 'CHAT_MESSAGE',
        channel: 'lesson',
        lesson_session_id: 'lesson-123'
      };

      const channelKey = getChannelKeyFromMessage(lessonMessage);
      expect(channelKey).toBe('lesson-123');
    });

    test('should construct channel key for global messages', () => {
      // Global messages: channel key = 'global'
      const globalMessage = {
        type: 'CHAT_MESSAGE',
        channel: 'global'
      };

      const channelKey = getChannelKeyFromMessage(globalMessage);
      expect(channelKey).toBe('global');
    });
  });

  describe('unread count increment logic', () => {
    test('should increment unread if window is closed', () => {
      // Chat window closed -> always increment unread
      const chatState = {
        isWindowOpen: false,
        activeChannel: 'session-abc'
      };

      const message = {
        type: 'CHAT_MESSAGE',
        channel: 'session',
        session_id: 'session-abc'
      };

      const messageChannelKey = getChannelKeyFromMessage(message);
      const shouldIncrement = !chatState.isWindowOpen || chatState.activeChannel !== messageChannelKey;

      expect(shouldIncrement).toBe(true);
    });

    test('should increment unread if viewing different channel', () => {
      // Window open but viewing different channel -> increment unread
      const chatState = {
        isWindowOpen: true,
        activeChannel: 'global'
      };

      const message = {
        type: 'CHAT_MESSAGE',
        channel: 'session',
        session_id: 'session-abc'
      };

      const messageChannelKey = getChannelKeyFromMessage(message);
      const shouldIncrement = !chatState.isWindowOpen || chatState.activeChannel !== messageChannelKey;

      expect(shouldIncrement).toBe(true);
    });

    test('should NOT increment unread if window open and viewing same channel', () => {
      // Window open AND viewing same channel -> do NOT increment
      const chatState = {
        isWindowOpen: true,
        activeChannel: 'session-abc'
      };

      const message = {
        type: 'CHAT_MESSAGE',
        channel: 'session',
        session_id: 'session-abc'
      };

      const messageChannelKey = getChannelKeyFromMessage(message);
      const shouldIncrement = !chatState.isWindowOpen || chatState.activeChannel !== messageChannelKey;

      expect(shouldIncrement).toBe(false);
    });

    test('should increment unread for global channel when window closed', () => {
      const chatState = {
        isWindowOpen: false,
        activeChannel: null
      };

      const message = {
        type: 'CHAT_MESSAGE',
        channel: 'global'
      };

      const messageChannelKey = getChannelKeyFromMessage(message);
      const shouldIncrement = !chatState.isWindowOpen || chatState.activeChannel !== messageChannelKey;

      expect(messageChannelKey).toBe('global');
      expect(shouldIncrement).toBe(true);
    });
  });

  describe('WebSocket integration', () => {
    test('action creators should be imported from sessionChatSlice', () => {
      // Verify action creators are available
      expect(addMessageFromWebSocket).toBeDefined();
      expect(incrementUnreadCount).toBeDefined();
      expect(typeof addMessageFromWebSocket).toBe('function');
      expect(typeof incrementUnreadCount).toBe('function');
    });

    test('addMessageFromWebSocket creates correct action', () => {
      const message = {
        id: 'msg-1',
        senderId: 'user-1',
        senderName: 'John Doe',
        message: 'Hello',
        channel: 'session',
        sessionId: 'session-abc',
        createdAt: '2026-01-26T12:00:00Z'
      };

      const action = addMessageFromWebSocket(message);
      expect(action.type).toBe('sessionChat/addMessageFromWebSocket');
      expect(action.payload).toEqual(message);
    });

    test('incrementUnreadCount creates correct action', () => {
      const action = incrementUnreadCount({ channel: 'session-abc' });
      expect(action.type).toBe('sessionChat/incrementUnreadCount');
      expect(action.payload).toEqual({ channel: 'session-abc' });
    });
  });
});
