import { configureStore, EnhancedStore } from '@reduxjs/toolkit'
import { act, render, screen } from '@testing-library/react'
import { Provider } from 'react-redux'
import { Participants } from './Participants'
import { zocksStoreConfig } from '../../../app/store'
import {
  activeSpeakersChanged,
  addRemoteParticipant,
  participantLocalTrackPublished,
  participantTrackPublished,
  setLocalParticipantId,
} from '../../../store/session/sessionSlice'
import { StreamKind, StreamSource } from '@zocks-communications/client-sdk-js'
import { changeParticipantsView, ParticipantsViewType } from '../../../store'
import { initStore } from '../../../testUtils'

const renderWithState = (store: EnhancedStore, gridPageSize: number = 25) => {
  return render(
    <Provider store={store}>
      <Participants gridPageSize={gridPageSize} />
    </Provider>
  )
}

test('renders the grid view when currently the grid view is active', () => {
  const store = configureStore(zocksStoreConfig)
  store.dispatch(changeParticipantsView(ParticipantsViewType.Grid))
  const { container } = renderWithState(store)

  expect(container.querySelector('.zocks__participants-grid-view')).toBeInTheDocument()
})

test('renders the speaker view when currently the speaker view is active', () => {
  const store = configureStore(zocksStoreConfig)
  store.dispatch(changeParticipantsView(ParticipantsViewType.Speaker))
  const { container } = renderWithState(store)

  expect(container.querySelector('.zocks__participants-speaker-view')).toBeInTheDocument()
})

test('renders the screen share view if the local participant is sharing their screen', () => {
  const store = configureStore(zocksStoreConfig)
  store.dispatch(setLocalParticipantId('testLocalParticipantId'))
  store.dispatch(
    participantLocalTrackPublished({
      trackId: 'screenShareTrackId',
      trackKind: StreamKind.VIDEO,
      trackSource: StreamSource.SCREEN_SHARE,
      trackIsMuted: false,
    })
  )
  const { container } = renderWithState(store)

  expect(container.querySelector('.zocks__participants-screen-share-view')).toBeInTheDocument()
  expect(screen.queryByRole('button', { name: 'Change to speaker view' })).not.toBeInTheDocument()
  expect(screen.queryByRole('button', { name: 'Change to grid view' })).not.toBeInTheDocument()
})

test('renders the screen share view if a remote participant is sharing their screen', () => {
  const store = configureStore(zocksStoreConfig)
  store.dispatch(
    addRemoteParticipant({ participantId: 'testRemoteParticipantId', participantName: 'testRemoteParticipantName' })
  )
  store.dispatch(
    participantTrackPublished({
      participantId: 'testRemoteParticipantId',
      trackId: 'screenShareTrackId',
      trackKind: StreamKind.VIDEO,
      trackSource: StreamSource.SCREEN_SHARE,
      trackIsMuted: false,
      trackIsSubscribed: true,
    })
  )
  const { container } = renderWithState(store)

  expect(container.querySelector('.zocks__participants-screen-share-view')).toBeInTheDocument()
  expect(screen.queryByRole('button', { name: 'Change to speaker view' })).not.toBeInTheDocument()
  expect(screen.queryByRole('button', { name: 'Change to grid view' })).not.toBeInTheDocument()
})

test('ordering by active speakers is not lost when switching between different participant views when there are no more active speakers', async () => {
  const store = initStore(4, ['Participant id: 3'])
  renderWithState(store, 4)
  act(() => {
    store.dispatch(activeSpeakersChanged([]))
  })

  expect(screen.getByText('Participant name: 3')).toBeInTheDocument()
  expect(screen.queryByText('Participant name: 2')).not.toBeInTheDocument()

  act(() => {
    store.dispatch(changeParticipantsView(ParticipantsViewType.Speaker))
  })

  expect(screen.getByTestId('participant1Element')).toHaveTextContent('Participant name: 3')
  expect(screen.queryByText('Participant name: 2')).not.toBeInTheDocument()
})
