import {
  ConnectionQuality,
  RoomState,
  SessionState,
  StreamKind,
  StreamSource,
} from '@zocks-communications/client-sdk-js'
import sessionReducer, {
  activeSpeakersChanged,
  addRemoteParticipant,
  clearParticipants,
  clearRoomId,
  connectionQualityChanged,
  participantLocalTrackPublished,
  participantLocalTrackUnPublished,
  participantTrackMuted,
  participantTrackUnMuted,
  participantTrackUnPublished,
  participantTrackPublished,
  participantTrackSubscribed,
  participantTrackUnsubscribed,
  removeRemoteParticipant,
  selectIsScreenSharing,
  selectScreenSharingParticipant,
  selectUnmutedRemoteParticipantAudioTracks,
  selectTracksForParticipant,
  setConnecting,
  setLocalParticipantId,
  setLocalParticipantName,
  setSessionState,
  setRoomId,
  setRoomName,
  clearRoomName,
  setActiveSession,
  clearActiveSession,
  setRecording,
  setSessionConfig,
} from './sessionSlice'
import { mockRootState, setupZocksSdkMocks } from '../../testUtils'
import { SessionModel } from './models'

afterEach(() => {
  jest.restoreAllMocks()
})

test('room has an initial state', () => {
  expect(sessionReducer(undefined, { type: 'unknown' })).toStrictEqual({
    roomId: null,
    roomName: null,
    activeSession: null,
    sessionConfig: null,
    sessionState: SessionState.DISCONNECTED,
    isConnecting: false,
    localParticipant: {
      id: null,
      name: null,
      connectionQuality: ConnectionQuality.EXCELLENT,
      tracks: {
        audioTracks: [],
        videoTracks: [],
        screenShareTrack: null,
      },
    },
    remoteParticipants: {},
    speakers: {
      activeSpeakers: [],
      lastSpeakers: [],
    },
  })
})

const state: SessionModel = {
  roomId: 'testRoomId',
  roomName: '',
  activeSession: null,
  sessionState: SessionState.CONNECTED,
  sessionConfig: null,
  isConnecting: false,
  localParticipant: {
    id: 'testLocalParticipantId',
    name: 'testLocalParticipantName',
    connectionQuality: ConnectionQuality.EXCELLENT,
    tracks: {
      audioTracks: [
        {
          id: 'testLocalAudioTrackId',
          isMuted: true,
          isSubscribed: true,
        },
      ],
      videoTracks: [
        {
          id: 'testLocalVideoTrackId',
          isMuted: true,
          isSubscribed: true,
        },
      ],
      screenShareTrack: null,
    },
  },
  remoteParticipants: {
    testRemoteParticipantId: {
      id: 'testRemoteParticipantId',
      name: 'testRemoteParticipantName',
      connectionQuality: ConnectionQuality.EXCELLENT,
      tracks: {
        audioTracks: [
          {
            id: 'testRemoteAudioTrackId',
            isMuted: true,
            isSubscribed: true,
          },
        ],
        videoTracks: [
          {
            id: 'testRemoteVideoTrackId',
            isMuted: true,
            isSubscribed: true,
          },
        ],
        screenShareTrack: null,
      },
    },
  },
  speakers: {
    activeSpeakers: [],
    lastSpeakers: [],
  },
}

test('handles session state changes', () => {
  const newState = sessionReducer(state, setSessionState(SessionState.DISCONNECTED))

  expect(newState.sessionState).toBe(RoomState.DISCONNECTED)
})

test('handles session config changes', () => {
  const newState = sessionReducer(state, setSessionConfig({ accountId: 'testAccountId' }))

  expect(newState.sessionConfig).toStrictEqual({ accountId: 'testAccountId' })
})

test('handles room id changes', () => {
  const newState = sessionReducer(state, setRoomId('newRoomId'))

  expect(newState.roomId).toBe('newRoomId')
})

test('handles room name changes', () => {
  const newState = sessionReducer(state, setRoomName('newRoomName'))

  expect(newState.roomName).toBe('newRoomName')
})

test('handles active session changes', () => {
  const newState = sessionReducer(
    state,
    setActiveSession({
      numberOfParticipants: 5,
      recording: null,
      sessionId: 'abcdef012345',
      createdAt: '2023-02-08T12:49:20.212613Z',
    })
  )

  expect(newState.activeSession).toEqual({
    numberOfParticipants: 5,
    recording: null,
    sessionId: 'abcdef012345',
    createdAt: '2023-02-08T12:49:20.212613Z',
  })
})

test('handles recording changes', () => {
  const newState = sessionReducer(state, setActiveSession({ recording: null }))
  const testState = sessionReducer(
    newState,
    setRecording({
      userId: 'user-id',
      fileId: 'abcdef012345',
      startedAt: '2023-02-08T12:49:20.212613Z',
    })
  )

  expect(testState.activeSession?.recording).toEqual({
    userId: 'user-id',
    fileId: 'abcdef012345',
    startedAt: '2023-02-08T12:49:20.212613Z',
  })
})

test('handles local participant id changes', () => {
  const newState = sessionReducer(state, setLocalParticipantId('newLocalParticipantId'))

  expect(newState.localParticipant.id).toBe('newLocalParticipantId')
})

test('handles local participant name changes', () => {
  const newState = sessionReducer(state, setLocalParticipantName('newLocalParticipantName'))

  expect(newState.localParticipant.name).toBe('newLocalParticipantName')

  const newStateWithoutName = sessionReducer(state, setLocalParticipantName())

  expect(newStateWithoutName.localParticipant.name).toBeNull()
})

test('sets the active speakers and last speakers if there were no speakers before', () => {
  const newState = sessionReducer(state, activeSpeakersChanged(['testLocalParticipantId']))

  expect(newState).toStrictEqual({
    ...state,
    speakers: { activeSpeakers: ['testLocalParticipantId'], lastSpeakers: ['testLocalParticipantId'] },
  })
})

test('extends last speakers and sets active speakers if there were different speakers before', () => {
  const newState = sessionReducer(
    { ...state, speakers: { activeSpeakers: [], lastSpeakers: ['testLastSpeakerParticipantId'] } },
    activeSpeakersChanged(['testLocalParticipantId'])
  )

  expect(newState).toStrictEqual({
    ...state,
    speakers: {
      activeSpeakers: ['testLocalParticipantId'],
      lastSpeakers: ['testLocalParticipantId', 'testLastSpeakerParticipantId'],
    },
  })
})

test('does not change last speakers but sets active speakers if the new last speakers are the same as before', () => {
  const newState = sessionReducer(
    { ...state, speakers: { activeSpeakers: [], lastSpeakers: ['testLocalParticipantId'] } },
    activeSpeakersChanged(['testLocalParticipantId'])
  )

  expect(newState).toStrictEqual({
    ...state,
    speakers: {
      activeSpeakers: ['testLocalParticipantId'],
      lastSpeakers: ['testLocalParticipantId'],
    },
  })
})

test('clears the active speakers and does not touch last speakers if there are no speakers anymore', () => {
  const newState = sessionReducer(
    { ...state, speakers: { activeSpeakers: ['testLocalParticipantId'], lastSpeakers: ['testLocalParticipantId'] } },
    activeSpeakersChanged([])
  )

  expect(newState).toStrictEqual({
    ...state,
    speakers: { activeSpeakers: [], lastSpeakers: ['testLocalParticipantId'] },
  })
})

test('clears room id', () => {
  const newState = sessionReducer(state, clearRoomId())

  expect(newState.roomId).toBeNull()
})

test('clears room name', () => {
  const newState = sessionReducer(state, clearRoomName())

  expect(newState.roomName).toBeNull()
})

test('clears active session', () => {
  const newState = sessionReducer({ ...state, activeSession: { recording: null } }, clearActiveSession())

  expect(newState.activeSession).toBeNull()
})

test('clears the local participant, remote participants and last speakers', () => {
  const newState = sessionReducer(
    { ...state, speakers: { activeSpeakers: [], lastSpeakers: ['testLocalParticipantId'] } },
    clearParticipants()
  )

  expect(newState.remoteParticipants).toEqual({})
  expect(newState.localParticipant).toStrictEqual({
    connectionQuality: 'excellent',
    id: null,
    name: null,
    tracks: {
      audioTracks: [],
      screenShareTrack: null,
      videoTracks: [],
    },
  })
  expect(newState.speakers.lastSpeakers).toEqual([])
})

test('sets if the participant is connecting or not', () => {
  const newState = sessionReducer(state, setConnecting(true))

  expect(newState.isConnecting).toBe(true)
})

test('adds a new local audio track when a new local audio stream is published', () => {
  const newState = sessionReducer(
    state,
    participantLocalTrackPublished({
      trackId: 'newAudioTrackId',
      trackSource: StreamSource.MICROPHONE,
      trackKind: StreamKind.AUDIO,
      trackIsMuted: false,
    })
  )

  expect(newState.localParticipant.tracks.audioTracks).toHaveLength(2)
  expect(newState.localParticipant.tracks.audioTracks[1].id).toBe('newAudioTrackId')
  expect(newState.localParticipant.tracks.audioTracks[1].isMuted).toBe(false)
})

test('adds a new local video track when a new local video track is published', () => {
  const newState = sessionReducer(
    state,
    participantLocalTrackPublished({
      trackId: 'newVideoTrackId',
      trackSource: StreamSource.CAMERA,
      trackKind: StreamKind.VIDEO,
      trackIsMuted: false,
    })
  )

  expect(newState.localParticipant.tracks.videoTracks).toHaveLength(2)
  expect(newState.localParticipant.tracks.videoTracks[1].id).toBe('newVideoTrackId')
  expect(newState.localParticipant.tracks.videoTracks[1].isMuted).toBe(false)
})

test('sets the local screen share track when the local screen share track is published', () => {
  const newState = sessionReducer(
    state,
    participantLocalTrackPublished({
      trackId: 'newScreenShareTrackId',
      trackSource: StreamSource.SCREEN_SHARE,
      trackKind: StreamKind.VIDEO,
      trackIsMuted: false,
    })
  )

  expect(newState.localParticipant.tracks.screenShareTrack).toStrictEqual({
    id: 'newScreenShareTrackId',
    isMuted: false,
    isSubscribed: true,
  })
})

test('does not change tracks when an unknown local track is published', () => {
  const newState = sessionReducer(
    state,
    participantLocalTrackPublished({
      trackId: 'unknownTrackId',
      trackSource: StreamSource.UNKNOWN,
      trackKind: StreamKind.UNKNOWN,
      trackIsMuted: false,
    })
  )

  expect(newState).toStrictEqual(state)
})

test('removes the local audio track when a local audio track is unpublished', () => {
  const newState = sessionReducer(
    state,
    participantLocalTrackUnPublished({
      trackId: 'testLocalAudioTrackId',
      trackSource: StreamSource.MICROPHONE,
      trackKind: StreamKind.AUDIO,
    })
  )

  expect(newState.localParticipant.tracks.audioTracks).toHaveLength(0)
})

test('removes the local video track when a local video track is unpublished', () => {
  const newState = sessionReducer(
    state,
    participantLocalTrackUnPublished({
      trackId: 'testLocalVideoTrackId',
      trackSource: StreamSource.CAMERA,
      trackKind: StreamKind.VIDEO,
    })
  )

  expect(newState.localParticipant.tracks.videoTracks).toHaveLength(0)
})

test('does not change tracks when an unknown local track is unpublished', () => {
  const newState = sessionReducer(
    state,
    participantLocalTrackUnPublished({
      trackId: 'unknownTrackId',
      trackSource: StreamSource.UNKNOWN,
      trackKind: StreamKind.UNKNOWN,
    })
  )

  expect(newState).toStrictEqual(state)
})

test('removes the remote audio track when a remote audio track is unpublished', () => {
  const newState = sessionReducer(
    state,
    participantTrackUnPublished({
      participantId: 'testRemoteParticipantId',
      trackId: 'testRemoteAudioTrackId',
      trackSource: StreamSource.MICROPHONE,
      trackKind: StreamKind.AUDIO,
    })
  )

  expect(newState.remoteParticipants['testRemoteParticipantId'].tracks.audioTracks).toHaveLength(0)
})

test('removes the remote video track when a remote video track is unpublished', () => {
  const newState = sessionReducer(
    state,
    participantTrackUnPublished({
      participantId: 'testRemoteParticipantId',
      trackId: 'testRemoteVideoTrackId',
      trackSource: StreamSource.CAMERA,
      trackKind: StreamKind.VIDEO,
    })
  )

  expect(newState.remoteParticipants['testRemoteParticipantId'].tracks.videoTracks).toHaveLength(0)
})

test('removes the remote screen share track when a remote screen share track is unpublished', () => {
  const newState = sessionReducer(
    state,
    participantTrackUnPublished({
      participantId: 'testRemoteParticipantId',
      trackId: 'testRemoteScreenShareTrackId',
      trackSource: StreamSource.SCREEN_SHARE,
      trackKind: StreamKind.VIDEO,
    })
  )

  expect(newState.remoteParticipants['testRemoteParticipantId'].tracks.screenShareTrack).toBeNull()
})

test('does not change remote participant tracks when an unknown track is unpublished', () => {
  const newState = sessionReducer(
    state,
    participantTrackUnPublished({
      participantId: 'testRemoteParticipantId',
      trackId: 'unknownTrackId',
      trackSource: StreamSource.UNKNOWN,
      trackKind: StreamKind.UNKNOWN,
    })
  )

  expect(newState).toStrictEqual(state)
})

test('does not change remote participant tracks when a track of an unknown participant is unpublished', () => {
  const newState = sessionReducer(
    state,
    participantTrackUnPublished({
      participantId: 'unknownRemoteParticipantId',
      trackId: 'unknownTrackId',
      trackSource: StreamSource.UNKNOWN,
      trackKind: StreamKind.UNKNOWN,
    })
  )

  expect(newState).toStrictEqual(state)
})

test('adds a new remote participant with default values', () => {
  const newState = sessionReducer(
    state,
    addRemoteParticipant({ participantId: 'newRemoteParticipantId', participantName: 'newRemoteParticipantName' })
  )

  expect(Object.keys(newState.remoteParticipants)).toHaveLength(2)
  expect(newState.remoteParticipants['testRemoteParticipantId']).toStrictEqual(
    state.remoteParticipants['testRemoteParticipantId']
  )
  expect(newState.remoteParticipants['newRemoteParticipantId']).toStrictEqual({
    id: 'newRemoteParticipantId',
    name: 'newRemoteParticipantName',
    connectionQuality: ConnectionQuality.EXCELLENT,
    tracks: {
      audioTracks: [],
      videoTracks: [],
      screenShareTrack: null,
    },
  })
})

test('removes a remote participant', () => {
  const newState = sessionReducer(state, removeRemoteParticipant({ participantId: 'testRemoteParticipantId' }))

  expect(newState.remoteParticipants).toEqual({})
})

test('creates a new remote participant audio track when a new remote audio track is published', () => {
  const newState = sessionReducer(
    state,
    participantTrackPublished({
      participantId: 'testRemoteParticipantId',
      trackId: 'newRemoteAudioTrackId',
      trackSource: StreamSource.MICROPHONE,
      trackKind: StreamKind.AUDIO,
      trackIsSubscribed: true,
      trackIsMuted: false,
    })
  )

  expect(newState.remoteParticipants['testRemoteParticipantId'].tracks.audioTracks).toHaveLength(2)
  expect(newState.remoteParticipants['testRemoteParticipantId'].tracks.audioTracks[1]).toStrictEqual({
    id: 'newRemoteAudioTrackId',
    isMuted: false,
    isSubscribed: true,
  })
})

test('creates a new remote participant video track when a new remote video track is published', () => {
  const newState = sessionReducer(
    state,
    participantTrackPublished({
      participantId: 'testRemoteParticipantId',
      trackId: 'newRemoteVideoTrackId',
      trackSource: StreamSource.CAMERA,
      trackKind: StreamKind.VIDEO,
      trackIsSubscribed: true,
      trackIsMuted: false,
    })
  )

  expect(newState.remoteParticipants['testRemoteParticipantId'].tracks.videoTracks).toHaveLength(2)
  expect(newState.remoteParticipants['testRemoteParticipantId'].tracks.videoTracks[1]).toStrictEqual({
    id: 'newRemoteVideoTrackId',
    isMuted: false,
    isSubscribed: true,
  })
})

test('sets the remote participant screen share track when a new remote screne share track is published', () => {
  const newState = sessionReducer(
    state,
    participantTrackPublished({
      participantId: 'testRemoteParticipantId',
      trackId: 'newRemoteScreenShareTrackId',
      trackSource: StreamSource.SCREEN_SHARE,
      trackKind: StreamKind.VIDEO,
      trackIsSubscribed: true,
      trackIsMuted: false,
    })
  )

  expect(newState.remoteParticipants['testRemoteParticipantId'].tracks.screenShareTrack).toStrictEqual({
    id: 'newRemoteScreenShareTrackId',
    isMuted: false,
    isSubscribed: true,
  })
})

test('does not change the remote participant when a track of unknown type is published', () => {
  const newState = sessionReducer(
    state,
    participantTrackPublished({
      participantId: 'testRemoteParticipantId',
      trackId: 'unknownTrackId',
      trackSource: StreamSource.UNKNOWN,
      trackKind: StreamKind.UNKNOWN,
      trackIsSubscribed: true,
      trackIsMuted: false,
    })
  )

  expect(newState).toStrictEqual(state)
})

test('does not change the state when an unknown remote participant publishes a track', () => {
  const newState = sessionReducer(
    state,
    participantTrackPublished({
      participantId: 'unknownRemoteParticipant',
      trackId: 'remoteAudioTrackId',
      trackSource: StreamSource.MICROPHONE,
      trackKind: StreamKind.AUDIO,
      trackIsSubscribed: true,
      trackIsMuted: false,
    })
  )

  expect(newState).toStrictEqual(state)
})

test('changes the subscription status of the track when subscribing to a remote audio track', () => {
  const newState = sessionReducer(
    {
      ...state,
      remoteParticipants: {
        testRemoteParticipantId: {
          id: 'testRemoteParticipantId',
          name: 'testRemoteParticipantName',
          connectionQuality: ConnectionQuality.EXCELLENT,
          tracks: {
            audioTracks: [
              {
                id: 'testRemoteAudioTrackId',
                isMuted: false,
                isSubscribed: false,
              },
            ],
            videoTracks: [
              {
                id: 'testRemoteVideoTrackId',
                isMuted: false,
                isSubscribed: false,
              },
            ],
            screenShareTrack: null,
          },
        },
      },
    },
    participantTrackSubscribed({
      participantId: 'testRemoteParticipantId',
      trackId: 'testRemoteAudioTrackId',
      trackIsMuted: false,
    })
  )

  expect(newState.remoteParticipants['testRemoteParticipantId'].tracks.audioTracks[0].isSubscribed).toBe(true)
  expect(newState.remoteParticipants['testRemoteParticipantId'].tracks.videoTracks[0].isSubscribed).toBe(false)
})

test('changes the subscription status of the track when subscribing to a remote video track', () => {
  const newState = sessionReducer(
    {
      ...state,
      remoteParticipants: {
        testRemoteParticipantId: {
          id: 'testRemoteParticipantId',
          name: 'testRemoteParticipantName',
          connectionQuality: ConnectionQuality.EXCELLENT,
          tracks: {
            audioTracks: [
              {
                id: 'testRemoteAudioTrackId',
                isMuted: false,
                isSubscribed: false,
              },
            ],
            videoTracks: [
              {
                id: 'testRemoteVideoTrackId',
                isMuted: false,
                isSubscribed: false,
              },
            ],
            screenShareTrack: null,
          },
        },
      },
    },
    participantTrackSubscribed({
      participantId: 'testRemoteParticipantId',
      trackId: 'testRemoteVideoTrackId',
      trackIsMuted: false,
    })
  )

  expect(newState.remoteParticipants['testRemoteParticipantId'].tracks.videoTracks[0].isSubscribed).toBe(true)
  expect(newState.remoteParticipants['testRemoteParticipantId'].tracks.audioTracks[0].isSubscribed).toBe(false)
})

test('changes the subscription status of the track when subscribing to a remote screen share track', () => {
  const newState = sessionReducer(
    {
      ...state,
      remoteParticipants: {
        testRemoteParticipantId: {
          id: 'testRemoteParticipantId',
          name: 'testRemoteParticipantName',
          connectionQuality: ConnectionQuality.EXCELLENT,
          tracks: {
            audioTracks: [],
            videoTracks: [],
            screenShareTrack: {
              id: 'testRemoteScreenShareTrackId',
              isMuted: false,
              isSubscribed: false,
            },
          },
        },
      },
    },
    participantTrackSubscribed({
      participantId: 'testRemoteParticipantId',
      trackId: 'testRemoteScreenShareTrackId',
      trackIsMuted: false,
    })
  )

  expect(newState.remoteParticipants['testRemoteParticipantId'].tracks.screenShareTrack!.isSubscribed).toBe(true)
})

test('does not change the state when subscribing to a track of an unknown participant', () => {
  const newState = sessionReducer(
    state,
    participantTrackSubscribed({
      participantId: 'unknownRemoteParticipantId',
      trackId: 'unknownRemoteTrackId',
      trackIsMuted: false,
    })
  )

  expect(newState).toStrictEqual(state)
})

test('does not change the state when subscribing to an unknown track', () => {
  const newState = sessionReducer(
    state,
    participantTrackSubscribed({
      participantId: 'testRemoteParticipantId',
      trackId: 'unknownRemoteTrackId',
      trackIsMuted: false,
    })
  )

  expect(newState).toStrictEqual(state)
})

test('mutes the subscribed track when the track is muted while subscribing to it', () => {
  const newState = sessionReducer(
    {
      ...state,
      remoteParticipants: {
        testRemoteParticipantId: {
          id: 'testRemoteParticipantId',
          name: 'testRemoteParticipantName',
          connectionQuality: ConnectionQuality.EXCELLENT,
          tracks: {
            audioTracks: [
              {
                id: 'testRemoteAudioTrackId',
                isMuted: true,
                isSubscribed: false,
              },
            ],
            videoTracks: [],
            screenShareTrack: null,
          },
        },
      },
    },
    participantTrackSubscribed({
      participantId: 'testRemoteParticipantId',
      trackId: 'testRemoteAudioTrackId',
      trackIsMuted: true,
    })
  )

  expect(newState.remoteParticipants['testRemoteParticipantId'].tracks.audioTracks[0].isMuted).toBe(true)
})

test('unmutes the subscribed track when the track is unmuted while subscribing to it', () => {
  const newState = sessionReducer(
    {
      ...state,
      remoteParticipants: {
        testRemoteParticipantId: {
          id: 'testRemoteParticipantId',
          name: 'testRemoteParticipantName',
          connectionQuality: ConnectionQuality.EXCELLENT,
          tracks: {
            audioTracks: [
              {
                id: 'testRemoteAudioTrackId',
                isMuted: true,
                isSubscribed: false,
              },
            ],
            videoTracks: [],
            screenShareTrack: null,
          },
        },
      },
    },
    participantTrackSubscribed({
      participantId: 'testRemoteParticipantId',
      trackId: 'testRemoteAudioTrackId',
      trackIsMuted: false,
    })
  )

  expect(newState.remoteParticipants['testRemoteParticipantId'].tracks.audioTracks[0].isMuted).toBe(false)
})

test('changes the subscription status of the track when unsubscribing from a remote audio track', () => {
  const newState = sessionReducer(
    state,
    participantTrackUnsubscribed({ participantId: 'testRemoteParticipantId', trackId: 'testRemoteAudioTrackId' })
  )

  expect(newState.remoteParticipants['testRemoteParticipantId'].tracks.audioTracks[0].isSubscribed).toBe(false)
  expect(newState.remoteParticipants['testRemoteParticipantId'].tracks.videoTracks[0].isSubscribed).toBe(true)
})

test('changes the subscription status of the track when unsubscribing from a remote video track', () => {
  const newState = sessionReducer(
    state,
    participantTrackUnsubscribed({ participantId: 'testRemoteParticipantId', trackId: 'testRemoteVideoTrackId' })
  )

  expect(newState.remoteParticipants['testRemoteParticipantId'].tracks.videoTracks[0].isSubscribed).toBe(false)
  expect(newState.remoteParticipants['testRemoteParticipantId'].tracks.audioTracks[0].isSubscribed).toBe(true)
})

test('changes the subscription status of the track when unsubscribing from a remote screen share track', () => {
  const newState = sessionReducer(
    {
      ...state,
      remoteParticipants: {
        testRemoteParticipantId: {
          id: 'testRemoteParticipantId',
          name: 'testRemoteParticipantName',
          connectionQuality: ConnectionQuality.EXCELLENT,
          tracks: {
            audioTracks: [],
            videoTracks: [],
            screenShareTrack: {
              id: 'testRemoteScreenShareTrackId',
              isMuted: false,
              isSubscribed: true,
            },
          },
        },
      },
    },
    participantTrackUnsubscribed({
      participantId: 'testRemoteParticipantId',
      trackId: 'testRemoteScreenShareTrackId',
    })
  )

  expect(newState.remoteParticipants['testRemoteParticipantId'].tracks.screenShareTrack!.isSubscribed).toBe(false)
})

test('does not change the state when unsubscribing from a track of an unknown participant', () => {
  const newState = sessionReducer(
    state,
    participantTrackUnsubscribed({
      participantId: 'unknownRemoteParticipantId',
      trackId: 'unknownRemoteTrackId',
    })
  )

  expect(newState).toStrictEqual(state)
})

test('does not change the state when unsubscribing from an unknown track', () => {
  const newState = sessionReducer(
    state,
    participantTrackUnsubscribed({
      participantId: 'testRemoteParticipantId',
      trackId: 'unknownRemoteTrackId',
    })
  )

  expect(newState).toStrictEqual(state)
})

test('mutes the local participant audio track, but not the video', () => {
  const newState = sessionReducer(
    {
      ...state,
      localParticipant: {
        id: 'testLocalParticipantId',
        name: 'testLocalParticipantName',
        connectionQuality: ConnectionQuality.EXCELLENT,
        tracks: {
          audioTracks: [
            {
              id: 'testLocalAudioTrackId',
              isMuted: false,
              isSubscribed: true,
            },
          ],
          videoTracks: [
            {
              id: 'testLocalVideoTrackId',
              isMuted: false,
              isSubscribed: true,
            },
          ],
          screenShareTrack: null,
        },
      },
    },
    participantTrackMuted({
      participantId: 'testLocalParticipantId',
      trackId: 'testLocalAudioTrackId',
    })
  )

  expect(newState.localParticipant.tracks.audioTracks[0].isMuted).toBe(true)
  expect(newState.localParticipant.tracks.videoTracks[0].isMuted).toBe(false)
})

test('mutes the local participant video track, but not the audio', () => {
  const newState = sessionReducer(
    {
      ...state,
      localParticipant: {
        id: 'testLocalParticipantId',
        name: 'testLocalParticipantName',
        connectionQuality: ConnectionQuality.EXCELLENT,
        tracks: {
          audioTracks: [
            {
              id: 'testLocalAudioTrackId',
              isMuted: false,
              isSubscribed: true,
            },
          ],
          videoTracks: [
            {
              id: 'testLocalVideoTrackId',
              isMuted: false,
              isSubscribed: true,
            },
          ],
          screenShareTrack: null,
        },
      },
    },
    participantTrackMuted({
      participantId: 'testLocalParticipantId',
      trackId: 'testLocalVideoTrackId',
    })
  )

  expect(newState.localParticipant.tracks.videoTracks[0].isMuted).toBe(true)
  expect(newState.localParticipant.tracks.audioTracks[0].isMuted).toBe(false)
})

test('unmutes the local participant audio track, but not the video', () => {
  const newState = sessionReducer(
    state,
    participantTrackUnMuted({
      participantId: 'testLocalParticipantId',
      trackId: 'testLocalAudioTrackId',
    })
  )

  expect(newState.localParticipant.tracks.audioTracks[0].isMuted).toBe(false)
  expect(newState.localParticipant.tracks.videoTracks[0].isMuted).toBe(true)
})

test('unmutes the local participant video track, but not the audio', () => {
  const newState = sessionReducer(
    state,
    participantTrackUnMuted({
      participantId: 'testLocalParticipantId',
      trackId: 'testLocalVideoTrackId',
    })
  )

  expect(newState.localParticipant.tracks.videoTracks[0].isMuted).toBe(false)
  expect(newState.localParticipant.tracks.audioTracks[0].isMuted).toBe(true)
})

test('mutes the remote participant audio track, but not the video', () => {
  const newState = sessionReducer(
    {
      ...state,
      remoteParticipants: {
        testRemoteParticipantId: {
          id: 'testRemoteParticipantId',
          name: 'testRemoteParticipantName',
          connectionQuality: ConnectionQuality.EXCELLENT,
          tracks: {
            audioTracks: [
              {
                id: 'testRemoteAudioTrackId',
                isMuted: false,
                isSubscribed: true,
              },
            ],
            videoTracks: [
              {
                id: 'testRemoteVideoTrackId',
                isMuted: false,
                isSubscribed: true,
              },
            ],
            screenShareTrack: null,
          },
        },
      },
    },
    participantTrackMuted({
      participantId: 'testRemoteParticipantId',
      trackId: 'testRemoteAudioTrackId',
    })
  )

  expect(newState.remoteParticipants['testRemoteParticipantId'].tracks.audioTracks[0].isMuted).toBe(true)
  expect(newState.remoteParticipants['testRemoteParticipantId'].tracks.videoTracks[0].isMuted).toBe(false)
})

test('mutes the remote participant video track, but not the audio', () => {
  const newState = sessionReducer(
    {
      ...state,
      remoteParticipants: {
        testRemoteParticipantId: {
          id: 'testRemoteParticipantId',
          name: 'testRemoteParticipantName',
          connectionQuality: ConnectionQuality.EXCELLENT,
          tracks: {
            audioTracks: [
              {
                id: 'testRemoteAudioTrackId',
                isMuted: false,
                isSubscribed: true,
              },
            ],
            videoTracks: [
              {
                id: 'testRemoteVideoTrackId',
                isMuted: false,
                isSubscribed: true,
              },
            ],
            screenShareTrack: null,
          },
        },
      },
    },
    participantTrackMuted({
      participantId: 'testRemoteParticipantId',
      trackId: 'testRemoteVideoTrackId',
    })
  )

  expect(newState.remoteParticipants['testRemoteParticipantId'].tracks.videoTracks[0].isMuted).toBe(true)
  expect(newState.remoteParticipants['testRemoteParticipantId'].tracks.audioTracks[0].isMuted).toBe(false)
})

test('unmutes the remote participant audio track, but not the video', () => {
  const newState = sessionReducer(
    state,
    participantTrackUnMuted({
      participantId: 'testRemoteParticipantId',
      trackId: 'testRemoteAudioTrackId',
    })
  )

  expect(newState.remoteParticipants['testRemoteParticipantId'].tracks.audioTracks[0].isMuted).toBe(false)
  expect(newState.remoteParticipants['testRemoteParticipantId'].tracks.videoTracks[0].isMuted).toBe(true)
})

test('unmutes the remote participant video track, but not the audio', () => {
  const newState = sessionReducer(
    state,
    participantTrackUnMuted({
      participantId: 'testRemoteParticipantId',
      trackId: 'testRemoteVideoTrackId',
    })
  )

  expect(newState.remoteParticipants['testRemoteParticipantId'].tracks.videoTracks[0].isMuted).toBe(false)
  expect(newState.remoteParticipants['testRemoteParticipantId'].tracks.audioTracks[0].isMuted).toBe(true)
})

test('does not do anything when a track of an unknown participant is muted', () => {
  const newState = sessionReducer(
    state,
    participantTrackMuted({
      participantId: 'unknownRemoteParticipant',
      trackId: 'unknownRemoteAudioTrackId',
    })
  )

  expect(newState).toStrictEqual(state)
})

test('does not do anything when a track of an unknown participant is unmuted', () => {
  const newState = sessionReducer(
    state,
    participantTrackUnMuted({
      participantId: 'unknownRemoteParticipant',
      trackId: 'unknownRemoteAudioTrackId',
    })
  )

  expect(newState).toStrictEqual(state)
})

test('does not do anything when an unknown track of a participant is muted', () => {
  const newState = sessionReducer(
    state,
    participantTrackMuted({
      participantId: 'testRemoteParticipantId',
      trackId: 'unknownRemoteAudioTrackId',
    })
  )

  expect(newState).toStrictEqual(state)
})

test('changes the connection quality of the local participant', () => {
  const newState = sessionReducer(
    state,
    connectionQualityChanged({ participantId: 'testLocalParticipantId', connectionQuality: ConnectionQuality.POOR })
  )

  expect(newState.localParticipant.connectionQuality).toBe(ConnectionQuality.POOR)
  expect(newState.remoteParticipants).toStrictEqual(state.remoteParticipants)
})

test('does not change state when the connection quality changes for an unknown participant', () => {
  const newState = sessionReducer(
    state,
    connectionQualityChanged({ participantId: 'unknownParticipantId', connectionQuality: ConnectionQuality.POOR })
  )

  expect(newState).toStrictEqual(state)
})

test('changes the connection quality of the remote participant', () => {
  const newState = sessionReducer(
    state,
    connectionQualityChanged({ participantId: 'testRemoteParticipantId', connectionQuality: ConnectionQuality.GOOD })
  )

  expect(newState.remoteParticipants['testRemoteParticipantId'].connectionQuality).toBe(ConnectionQuality.GOOD)
  expect(newState.localParticipant).toStrictEqual(state.localParticipant)
})

test('selectTracksForParticipant selects audio, video and screen share tracks for local participant if available', () => {
  const { mockGetSessionByRoomId, mockLocalAudioTrack, mockLocalVideoTrack, mockLocalScreenShareTrack } =
    setupZocksSdkMocks()
  const localParticipantWithAllTracks = {
    ...state.localParticipant,
    tracks: {
      audioTracks: [
        {
          id: 'testLocalAudioTrackId',
          isMuted: false,
          isSubscribed: true,
        },
      ],
      videoTracks: [
        {
          id: 'testLocalVideoTrackId',
          isMuted: false,
          isSubscribed: true,
        },
      ],
      screenShareTrack: {
        id: 'testLocalScreenShareTrackId',
        isMuted: false,
        isSubscribed: true,
      },
    },
  }

  const tracks = selectTracksForParticipant({ ...mockRootState, session: state }, localParticipantWithAllTracks)

  expect(mockGetSessionByRoomId).toHaveBeenCalledTimes(1)
  expect(mockGetSessionByRoomId).toHaveBeenCalledWith('testRoomId')
  expect(tracks).toStrictEqual({
    audioTracks: [{ track: mockLocalAudioTrack, isMuted: false, isSubscribed: true }],
    videoTracks: [{ track: mockLocalVideoTrack, isMuted: false, isSubscribed: true }],
    primaryAudioTrack: { track: mockLocalAudioTrack, isMuted: false, isSubscribed: true },
    primaryVideoTrack: { track: mockLocalVideoTrack, isMuted: false, isSubscribed: true },
    screenShareTrack: { track: mockLocalScreenShareTrack, isMuted: false, isSubscribed: true },
  })
})

test('selectTracksForParticipant can select muted local audio and video tracks for primary tracks', () => {
  const { mockGetSessionByRoomId, mockLocalAudioTrack, mockLocalVideoTrack } = setupZocksSdkMocks()
  const localParticipantWithMutedTracks = {
    ...state.localParticipant,
    tracks: {
      audioTracks: [
        {
          id: 'testLocalAudioTrackId',
          isMuted: true,
          isSubscribed: true,
        },
      ],
      videoTracks: [
        {
          id: 'testLocalVideoTrackId',
          isMuted: true,
          isSubscribed: true,
        },
      ],
    },
  }

  const tracks = selectTracksForParticipant({ ...mockRootState, session: state }, localParticipantWithMutedTracks)

  expect(mockGetSessionByRoomId).toHaveBeenCalledTimes(1)
  expect(mockGetSessionByRoomId).toHaveBeenCalledWith('testRoomId')
  expect(tracks).toStrictEqual({
    audioTracks: [{ track: mockLocalAudioTrack, isMuted: true, isSubscribed: true }],
    videoTracks: [{ track: mockLocalVideoTrack, isMuted: true, isSubscribed: true }],
    primaryAudioTrack: { track: mockLocalAudioTrack, isMuted: true, isSubscribed: true },
    primaryVideoTrack: { track: mockLocalVideoTrack, isMuted: true, isSubscribed: true },
    screenShareTrack: null,
  })
})

test('selectTracksForParticipant selects audio, video and screen share tracks for remote participant if available', () => {
  const { mockGetSessionByRoomId, mockRemoteAudioTrack, mockRemoteVideoTrack, mockRemoteScreenShareTrack } =
    setupZocksSdkMocks()

  const remoteParticipantWithAllTracks = {
    ...state.remoteParticipants['testRemoteParticipantId'],
    tracks: {
      audioTracks: [
        {
          id: 'testRemoteAudioTrackId',
          isMuted: false,
          isSubscribed: true,
        },
      ],
      videoTracks: [
        {
          id: 'testRemoteVideoTrackId',
          isMuted: false,
          isSubscribed: true,
        },
      ],
      screenShareTrack: {
        id: 'testRemoteScreenShareTrackId',
        isMuted: false,
        isSubscribed: true,
      },
    },
  }
  const tracks = selectTracksForParticipant({ ...mockRootState, session: state }, remoteParticipantWithAllTracks)

  expect(mockGetSessionByRoomId).toHaveBeenCalledTimes(1)
  expect(mockGetSessionByRoomId).toHaveBeenCalledWith('testRoomId')
  expect(tracks).toStrictEqual({
    audioTracks: [{ track: mockRemoteAudioTrack, isMuted: false, isSubscribed: true }],
    videoTracks: [{ track: mockRemoteVideoTrack, isMuted: false, isSubscribed: true }],
    primaryAudioTrack: { track: mockRemoteAudioTrack, isMuted: false, isSubscribed: true },
    primaryVideoTrack: { track: mockRemoteVideoTrack, isMuted: false, isSubscribed: true },
    screenShareTrack: { track: mockRemoteScreenShareTrack, isMuted: false, isSubscribed: true },
  })
})

test('selectTracksForParticipant can select muted remote audio and video tracks for primary tracks', () => {
  const { mockGetSessionByRoomId, mockRemoteAudioTrack, mockRemoteVideoTrack } = setupZocksSdkMocks()

  const remoteParticipantWithAllTracks = {
    ...state.remoteParticipants['testRemoteParticipantId'],
    tracks: {
      audioTracks: [
        {
          id: 'testRemoteAudioTrackId',
          isMuted: true,
          isSubscribed: true,
        },
      ],
      videoTracks: [
        {
          id: 'testRemoteVideoTrackId',
          isMuted: true,
          isSubscribed: true,
        },
      ],
      screenShareTrack: null,
    },
  }
  const tracks = selectTracksForParticipant({ ...mockRootState, session: state }, remoteParticipantWithAllTracks)

  expect(mockGetSessionByRoomId).toHaveBeenCalledTimes(1)
  expect(mockGetSessionByRoomId).toHaveBeenCalledWith('testRoomId')
  expect(tracks).toStrictEqual({
    audioTracks: [{ track: mockRemoteAudioTrack, isMuted: true, isSubscribed: true }],
    videoTracks: [{ track: mockRemoteVideoTrack, isMuted: true, isSubscribed: true }],
    primaryAudioTrack: { track: mockRemoteAudioTrack, isMuted: true, isSubscribed: true },
    primaryVideoTrack: { track: mockRemoteVideoTrack, isMuted: true, isSubscribed: true },
    screenShareTrack: null,
  })
})

test('selectTracksForParticipant can select unsubscribed remote audio and video tracks for primary tracks', () => {
  const { mockGetSessionByRoomId, mockRemoteAudioTrack, mockRemoteVideoTrack } = setupZocksSdkMocks()

  const remoteParticipantWithAllTracks = {
    ...state.remoteParticipants['testRemoteParticipantId'],
    tracks: {
      audioTracks: [
        {
          id: 'testRemoteAudioTrackId',
          isMuted: false,
          isSubscribed: false,
        },
      ],
      videoTracks: [
        {
          id: 'testRemoteVideoTrackId',
          isMuted: false,
          isSubscribed: false,
        },
      ],
      screenShareTrack: null,
    },
  }
  const tracks = selectTracksForParticipant({ ...mockRootState, session: state }, remoteParticipantWithAllTracks)

  expect(mockGetSessionByRoomId).toHaveBeenCalledTimes(1)
  expect(mockGetSessionByRoomId).toHaveBeenCalledWith('testRoomId')
  expect(tracks).toStrictEqual({
    audioTracks: [{ track: mockRemoteAudioTrack, isMuted: false, isSubscribed: false }],
    videoTracks: [{ track: mockRemoteVideoTrack, isMuted: false, isSubscribed: false }],
    primaryAudioTrack: { track: mockRemoteAudioTrack, isMuted: false, isSubscribed: false },
    primaryVideoTrack: { track: mockRemoteVideoTrack, isMuted: false, isSubscribed: false },
    screenShareTrack: null,
  })
})

test('selectTracksForParticipant does not select tracks if tracks are not available', () => {
  const { mockGetSessionByRoomId } = setupZocksSdkMocks()
  const localParticipantWithoutTracks = {
    id: 'testLocalParticipantId',
    name: 'testLocalParticipantName',
    connectionQuality: ConnectionQuality.EXCELLENT,
    isSpeaking: false,
    tracks: {
      audioTracks: [
        {
          id: 'unknownAudioTrackId',
          isMuted: false,
          isSubscribed: false,
        },
      ],
      videoTracks: [
        {
          id: 'unknownVideoTrackId',
          isMuted: false,
          isSubscribed: false,
        },
      ],
      screenShareTrack: {
        id: 'unknownScreenShareTrackId',
        isMuted: false,
        isSubscribed: false,
      },
    },
  }

  const tracks = selectTracksForParticipant(
    {
      ...mockRootState,
      session: {
        ...state,
        localParticipant: localParticipantWithoutTracks,
      },
    },
    localParticipantWithoutTracks
  )

  expect(mockGetSessionByRoomId).toHaveBeenCalledTimes(1)
  expect(mockGetSessionByRoomId).toHaveBeenCalledWith('testRoomId')
  expect(tracks).toStrictEqual({
    audioTracks: [],
    videoTracks: [],
    primaryAudioTrack: null,
    primaryVideoTrack: null,
    screenShareTrack: null,
  })
})

test('screen sharing is on when either the local participant or one of the remote participants share their screen', () => {
  const stateWithLocalParticipantScreenSharing = {
    ...state,
    localParticipant: {
      ...state.localParticipant,
      tracks: {
        audioTracks: [],
        videoTracks: [],
        screenShareTrack: {
          id: 'testLocalScreenShareTrackId',
          isMuted: false,
          isSubscribed: true,
        },
      },
    },
  }
  const stateWithRemoteParticipantScreenSharing = {
    ...state,
    remoteParticipants: {
      testRemoteParticipantId: {
        ...state.remoteParticipants.testRemoteParticipantId,
        tracks: {
          audioTracks: [],
          videoTracks: [],
          screenShareTrack: {
            id: 'testRemoteScreenShareTrackId',
            isMuted: false,
            isSubscribed: true,
          },
        },
      },
    },
  }

  expect(selectIsScreenSharing({ ...mockRootState, session: stateWithLocalParticipantScreenSharing })).toBe(true)
  expect(selectIsScreenSharing({ ...mockRootState, session: stateWithRemoteParticipantScreenSharing })).toBe(true)
})

test('screen sharing is off when neither the local nor the remote participants share their screen', () => {
  expect(selectIsScreenSharing({ ...mockRootState, session: state })).toBe(false)
})

test('selectScreenSharingParticipant selects the local participant if the local participant is sharing their screen', () => {
  const stateWithLocalParticipantScreenSharing = {
    ...state,
    localParticipant: {
      ...state.localParticipant,
      tracks: {
        audioTracks: [],
        videoTracks: [],
        screenShareTrack: {
          id: 'testLocalScreenShareTrackId',
          isMuted: false,
          isSubscribed: true,
        },
      },
    },
  }

  expect(
    selectScreenSharingParticipant({ ...mockRootState, session: stateWithLocalParticipantScreenSharing })
  ).toStrictEqual(stateWithLocalParticipantScreenSharing.localParticipant)
})

test('selectScreenSharingParticipant selects the remote participant if a remote participant is sharing their screen', () => {
  const stateWithRemoteParticipantScreenSharing = {
    ...state,
    remoteParticipants: {
      testRemoteParticipantId: {
        ...state.remoteParticipants.testRemoteParticipantId,
        tracks: {
          audioTracks: [],
          videoTracks: [],
          screenShareTrack: {
            id: 'testRemoteScreenShareTrackId',
            isMuted: false,
            isSubscribed: true,
          },
        },
      },
    },
  }

  expect(
    selectScreenSharingParticipant({ ...mockRootState, session: stateWithRemoteParticipantScreenSharing })
  ).toStrictEqual(stateWithRemoteParticipantScreenSharing.remoteParticipants.testRemoteParticipantId)
})

test('selectScreenSharingParticipant does not select a participant if noone is sharing their screen', () => {
  expect(selectScreenSharingParticipant({ ...mockRootState, session: state })).toBeNull()
})

test('selectSpeakingRemoteParticipantAudioTracks selects the first remote participant audio track which is subscribed and not muted', () => {
  const { mockGetSessionByRoomId, mockRemoteAudioTrack } = setupZocksSdkMocks()

  const stateWithRemoteParticipantAudio = {
    ...state,
    remoteParticipants: {
      testRemoteParticipantId: {
        ...state.remoteParticipants.testRemoteParticipantId,
        tracks: {
          audioTracks: [
            {
              id: 'testRemoteAudioTrackId',
              isMuted: false,
              isSubscribed: true,
            },
          ],
          videoTracks: [],
          screenShareTrack: null,
        },
      },
    },
  }
  const tracks = selectUnmutedRemoteParticipantAudioTracks({
    ...mockRootState,
    session: stateWithRemoteParticipantAudio,
  })

  expect(mockGetSessionByRoomId).toHaveBeenCalledTimes(1)
  expect(mockGetSessionByRoomId).toHaveBeenCalledWith('testRoomId')
  expect(tracks).toStrictEqual([{ track: mockRemoteAudioTrack, isMuted: false, isSubscribed: true }])
})

test('selectSpeakingRemoteParticipantAudioTracks does not select the audio track if it is not available', () => {
  const { mockGetSessionByRoomId } = setupZocksSdkMocks()

  const stateWithRemoteParticipantAudio = {
    ...state,
    remoteParticipants: {
      testRemoteParticipantId: {
        ...state.remoteParticipants.testRemoteParticipantId,
        tracks: {
          audioTracks: [
            {
              id: 'unknownRemoteAudioTrackId',
              isMuted: false,
              isSubscribed: true,
            },
          ],
          videoTracks: [],
          screenShareTrack: null,
        },
      },
    },
  }
  const tracks = selectUnmutedRemoteParticipantAudioTracks({
    ...mockRootState,
    session: stateWithRemoteParticipantAudio,
  })

  expect(mockGetSessionByRoomId).toHaveBeenCalledTimes(1)
  expect(mockGetSessionByRoomId).toHaveBeenCalledWith('testRoomId')
  expect(tracks).toStrictEqual([])
})

test('selectSpeakingRemoteParticipantAudioTracks does not select tracks if there are no audio tracks', () => {
  const { mockGetSessionByRoomId } = setupZocksSdkMocks()

  const stateWithRemoteParticipantAudio = {
    ...state,
    remoteParticipants: {
      testRemoteParticipantId: {
        ...state.remoteParticipants.testRemoteParticipantId,
        tracks: {
          audioTracks: [],
          videoTracks: [],
          screenShareTrack: null,
        },
      },
    },
  }
  const tracks = selectUnmutedRemoteParticipantAudioTracks({
    ...mockRootState,
    session: stateWithRemoteParticipantAudio,
  })

  expect(mockGetSessionByRoomId).toHaveBeenCalledTimes(1)
  expect(mockGetSessionByRoomId).toHaveBeenCalledWith('testRoomId')
  expect(tracks).toStrictEqual([])
})

test('selectSpeakingRemoteParticipantAudioTracks does not select the audio track if the track is muted', () => {
  const { mockGetSessionByRoomId } = setupZocksSdkMocks()

  const stateWithRemoteParticipantAudio = {
    ...state,
    remoteParticipants: {
      testRemoteParticipantId: {
        ...state.remoteParticipants.testRemoteParticipantId,
        tracks: {
          audioTracks: [
            {
              id: 'testRemoteAudioTrackId',
              isMuted: true,
              isSubscribed: true,
            },
          ],
          videoTracks: [],
          screenShareTrack: null,
        },
      },
    },
  }
  const tracks = selectUnmutedRemoteParticipantAudioTracks({
    ...mockRootState,
    session: stateWithRemoteParticipantAudio,
  })

  expect(mockGetSessionByRoomId).toHaveBeenCalledTimes(1)
  expect(mockGetSessionByRoomId).toHaveBeenCalledWith('testRoomId')
  expect(tracks).toStrictEqual([])
})

test('selectSpeakingRemoteParticipantAudioTracks does not select the audio track if it is not subscribed', () => {
  const { mockGetSessionByRoomId } = setupZocksSdkMocks()

  const stateWithRemoteParticipantAudio = {
    ...state,
    remoteParticipants: {
      testRemoteParticipantId: {
        ...state.remoteParticipants.testRemoteParticipantId,
        tracks: {
          audioTracks: [
            {
              id: 'testRemoteAudioTrackId',
              isMuted: false,
              isSubscribed: false,
            },
          ],
          videoTracks: [],
          screenShareTrack: null,
        },
      },
    },
  }
  const tracks = selectUnmutedRemoteParticipantAudioTracks({
    ...mockRootState,
    session: stateWithRemoteParticipantAudio,
  })

  expect(mockGetSessionByRoomId).toHaveBeenCalledTimes(1)
  expect(mockGetSessionByRoomId).toHaveBeenCalledWith('testRoomId')
  expect(tracks).toStrictEqual([])
})
