import transcriptReducer, {
  clearRemoteParticipantTranscription,
  clearTranscription,
  selectParticipantTranscripts,
  selectTranscriptionInProgress,
  selectTranscriptionServiceIsEnabled,
  selectTranscriptionServiceIsLoading,
  setTranscriptionInProgress,
  setTranscriptionServiceEnabled,
  setTranscriptionServiceIsLoading,
  transcriptionReceived,
} from './transcriptSlice'
import { SessionTranscriptModel } from './models'
import { TranscriptionResult } from '@zocks-communications/client-sdk-js'
import { mockRootState } from '../../testUtils'

const mockTranscriptionResult: TranscriptionResult = {
  resultId: 'testResultId',
  isFinal: true,
  startTime: 0,
  endTime: 2,
  transcript: 'test',
  items: [
    {
      content: 'test',
      isStable: true,
    },
  ],
}

test('handles receiving final transcription results', () => {
  const state: SessionTranscriptModel = {
    transcriptionServiceIsEnabled: true,
    transcriptionServiceIsLoading: false,
    transcriptionInProgress: true,
    transcripts: {},
  }

  const newState = transcriptReducer(
    state,
    transcriptionReceived({ participantId: 'testLocalParticipantId', transcriptionResult: mockTranscriptionResult })
  )

  expect(newState).toStrictEqual({
    ...state,
    transcripts: {
      testLocalParticipantId: {
        partialTranscript: null,
        finalTranscripts: [mockTranscriptionResult],
      },
    },
  })
})
test('handles receiving partial transcription results', () => {
  const state: SessionTranscriptModel = {
    transcriptionServiceIsEnabled: true,
    transcriptionServiceIsLoading: false,
    transcriptionInProgress: true,
    transcripts: {},
  }

  const newState = transcriptReducer(
    state,
    transcriptionReceived({
      participantId: 'testLocalParticipantId',
      transcriptionResult: { ...mockTranscriptionResult, isFinal: false },
    })
  )

  expect(newState).toStrictEqual({
    ...state,
    transcripts: {
      testLocalParticipantId: {
        partialTranscript: { ...mockTranscriptionResult, isFinal: false },
        finalTranscripts: [],
      },
    },
  })
})
test('handles receiving transcription results for a participant with already existing results', () => {
  const state: SessionTranscriptModel = {
    transcriptionServiceIsEnabled: true,
    transcriptionServiceIsLoading: false,
    transcriptionInProgress: true,
    transcripts: {
      testLocalParticipantId: {
        partialTranscript: { ...mockTranscriptionResult, isFinal: false },
        finalTranscripts: [],
      },
    },
  }

  const newState = transcriptReducer(
    state,
    transcriptionReceived({
      participantId: 'testLocalParticipantId',
      transcriptionResult: { ...mockTranscriptionResult },
    })
  )

  expect(newState).toStrictEqual({
    ...state,
    transcripts: {
      testLocalParticipantId: {
        partialTranscript: null,
        finalTranscripts: [mockTranscriptionResult],
      },
    },
  })
})

test('handles transcription service enabled state changes', () => {
  const state: SessionTranscriptModel = {
    transcriptionServiceIsEnabled: true,
    transcriptionServiceIsLoading: false,
    transcriptionInProgress: true,
    transcripts: {},
  }

  const newState = transcriptReducer(state, setTranscriptionServiceEnabled(false))

  expect(newState.transcriptionServiceIsEnabled).toBe(false)
})

test('handles transcription service loading state changes', () => {
  const state: SessionTranscriptModel = {
    transcriptionServiceIsEnabled: true,
    transcriptionServiceIsLoading: false,
    transcriptionInProgress: true,
    transcripts: {},
  }

  const newState = transcriptReducer(state, setTranscriptionServiceIsLoading(true))

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

test('handles transcription in progress state changes', () => {
  const state: SessionTranscriptModel = {
    transcriptionServiceIsEnabled: true,
    transcriptionServiceIsLoading: false,
    transcriptionInProgress: false,
    transcripts: {},
  }

  const newState = transcriptReducer(state, setTranscriptionInProgress(true))

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

test('clears partial transcriptions when transcription is not in progress anymore', () => {
  const state: SessionTranscriptModel = {
    transcriptionServiceIsEnabled: true,
    transcriptionServiceIsLoading: false,
    transcriptionInProgress: true,
    transcripts: {
      testLocalParticipantId: {
        partialTranscript: mockTranscriptionResult,
        finalTranscripts: [],
      },
    },
  }

  const newState = transcriptReducer(state, setTranscriptionInProgress(false))

  expect(newState.transcripts.testLocalParticipantId.partialTranscript).toBeNull()
})

test('clears transcriptions for everyone and disables transcription service', () => {
  const state: SessionTranscriptModel = {
    transcriptionServiceIsEnabled: true,
    transcriptionServiceIsLoading: false,
    transcriptionInProgress: true,
    transcripts: {
      testLocalParticipantId: {
        partialTranscript: mockTranscriptionResult,
        finalTranscripts: [],
      },
      testRemoteParticipantId: {
        partialTranscript: null,
        finalTranscripts: [mockTranscriptionResult],
      },
    },
  }

  const newState = transcriptReducer(state, clearTranscription())

  expect(newState).toStrictEqual({
    transcriptionServiceIsEnabled: false,
    transcriptionServiceIsLoading: false,
    transcriptionInProgress: true,
    transcripts: {},
  })
})

test('clears transcriptions for a specific remote participant', () => {
  const state: SessionTranscriptModel = {
    transcriptionServiceIsEnabled: true,
    transcriptionServiceIsLoading: false,
    transcriptionInProgress: true,
    transcripts: {
      testLocalParticipantId: {
        partialTranscript: mockTranscriptionResult,
        finalTranscripts: [],
      },
      testRemoteParticipantId: {
        partialTranscript: null,
        finalTranscripts: [mockTranscriptionResult],
      },
    },
  }

  const newState = transcriptReducer(
    state,
    clearRemoteParticipantTranscription({ participantId: 'testRemoteParticipantId' })
  )

  expect(newState).toStrictEqual({
    transcriptionServiceIsEnabled: true,
    transcriptionServiceIsLoading: false,
    transcriptionInProgress: true,
    transcripts: {
      testLocalParticipantId: {
        partialTranscript: mockTranscriptionResult,
        finalTranscripts: [],
      },
    },
  })
})

test('selectParticipantTranscripts selects the transcripts of the participant if they have transcripts', () => {
  const state: SessionTranscriptModel = {
    transcriptionServiceIsEnabled: true,
    transcriptionServiceIsLoading: false,
    transcriptionInProgress: true,
    transcripts: {
      testLocalParticipantId: {
        partialTranscript: mockTranscriptionResult,
        finalTranscripts: [mockTranscriptionResult],
      },
    },
  }

  const selectedTranscripts = selectParticipantTranscripts(
    { ...mockRootState, transcript: state },
    'testLocalParticipantId'
  )

  expect(selectedTranscripts).toStrictEqual({
    partialTranscript: mockTranscriptionResult,
    finalTranscripts: [mockTranscriptionResult],
  })
})

test('selectParticipantTranscripts selects empty transcripts if the participant does not have transcipts yet', () => {
  const state: SessionTranscriptModel = {
    transcriptionServiceIsEnabled: true,
    transcriptionServiceIsLoading: false,
    transcriptionInProgress: true,
    transcripts: {},
  }

  const selectedTranscripts = selectParticipantTranscripts(
    { ...mockRootState, transcript: state },
    'testLocalParticipantId'
  )

  expect(selectedTranscripts).toStrictEqual({
    partialTranscript: null,
    finalTranscripts: [],
  })
})

test('selectTranscriptionInProgress selects transcription in progress state', () => {
  const state: SessionTranscriptModel = {
    transcriptionServiceIsEnabled: true,
    transcriptionServiceIsLoading: false,
    transcriptionInProgress: true,
    transcripts: {},
  }

  expect(selectTranscriptionInProgress({ ...mockRootState, transcript: state })).toBe(true)
})

test('selectTranscriptionServiceIsEnabled selects transcription service enabled state', () => {
  const state: SessionTranscriptModel = {
    transcriptionServiceIsEnabled: true,
    transcriptionServiceIsLoading: false,
    transcriptionInProgress: true,
    transcripts: {},
  }

  expect(selectTranscriptionServiceIsEnabled({ ...mockRootState, transcript: state })).toBe(true)
})

test('selectTranscriptionServiceIsLoading selects transcription service loading state', () => {
  const state: SessionTranscriptModel = {
    transcriptionServiceIsEnabled: true,
    transcriptionServiceIsLoading: true,
    transcriptionInProgress: true,
    transcripts: {},
  }

  expect(selectTranscriptionServiceIsLoading({ ...mockRootState, transcript: state })).toBe(true)
})
