import { createSlice, PayloadAction } from '@reduxjs/toolkit'
import { RootState } from '../../app/store'
import { ParticipantTranscriptModel, SessionTranscriptModel } from './models'
import {
  RemoveParticipantTranscriptionAction,
  TranscriptionEnableAction,
  TranscriptionReceivedAction,
} from './actionModels'
import { TranscriptionResult } from '@zocks-communications/client-sdk-js'

const initialState: SessionTranscriptModel = {
  localStreamTranscriptionStatus: {
    serviceEnabled: false,
    serviceLoading: false,
    autoEnabled: false,
    transcriptionInProgress: false,
  },
  displayTranscriptions: false,
  transcripts: {},
}

export const transcriptSlice = createSlice({
  name: 'transcript',
  initialState,
  reducers: {
    transcriptionReceived: (state, action: PayloadAction<TranscriptionReceivedAction>) => {
      const { participantId, transcriptionResult } = action.payload
      if (!state.transcripts[participantId]) {
        state.transcripts[participantId] = { finalTranscripts: [], partialTranscript: null }
      }
      const participantTranscripts = state.transcripts[participantId]
      if (transcriptionResult.isFinal) {
        participantTranscripts.finalTranscripts.push(transcriptionResult)
        participantTranscripts.partialTranscript = null
      } else {
        participantTranscripts.partialTranscript = transcriptionResult
      }
    },
    setTranscriptionServiceEnabled: (state, action: PayloadAction<TranscriptionEnableAction>) => {
      const { enabled, autoEnable } = action.payload
      state.localStreamTranscriptionStatus.serviceEnabled = enabled
      if (enabled) {
        state.localStreamTranscriptionStatus.autoEnabled = !!autoEnable
      }
    },
    setTranscriptionServiceIsLoading: (state, action: PayloadAction<boolean>) => {
      state.localStreamTranscriptionStatus.serviceLoading = action.payload
    },
    setDisplayTranscriptions: (state, action: PayloadAction<boolean>) => {
      state.displayTranscriptions = action.payload
    },
    setTranscriptionInProgress: (state, action: PayloadAction<boolean>) => {
      const inProgress = action.payload
      state.localStreamTranscriptionStatus.transcriptionInProgress = inProgress
      if (!inProgress) {
        for (const transcript of Object.values(state.transcripts)) {
          transcript.partialTranscript = null
        }
      }
    },
    clearTranscription: (state) => {
      state.transcripts = {}
      state.localStreamTranscriptionStatus.serviceEnabled = false
      state.localStreamTranscriptionStatus.autoEnabled = false
    },
    clearRemoteParticipantTranscription: (state, action: PayloadAction<RemoveParticipantTranscriptionAction>) => {
      const { participantId } = action.payload
      delete state.transcripts[participantId]
    },
  },
})

export const {
  clearRemoteParticipantTranscription,
  clearTranscription,
  setDisplayTranscriptions,
  setTranscriptionServiceEnabled,
  setTranscriptionServiceIsLoading,
  setTranscriptionInProgress,
  transcriptionReceived,
} = transcriptSlice.actions

export const selectLocalStreamTranscriptionStatus = (state: RootState) =>
  state.transcript.localStreamTranscriptionStatus

export const selectDisplayTranscriptions = (state: RootState) => state.transcript.displayTranscriptions
export const selectTranscripts = (state: RootState) => state.transcript.transcripts

export const selectParticipantTranscripts = (
  state: RootState,
  participantId: string,
  since: number = 0
): ParticipantTranscriptModel => {
  const { transcripts } = state.transcript
  if (!transcripts[participantId]) {
    return { finalTranscripts: [], partialTranscript: null }
  }
  const participantTranscripts = transcripts[participantId]
  return since ? getTranscriptsSince(participantTranscripts, since) : participantTranscripts
}

const getTranscriptsSince = (transcripts: ParticipantTranscriptModel, since: number): ParticipantTranscriptModel => {
  const now = Date.now()
  const finalTranscripts = transcripts.finalTranscripts.filter((t) => transcriptCreatedSince(t, now, since))
  const partialTranscript =
    transcripts.partialTranscript && transcriptCreatedSince(transcripts.partialTranscript, now, since)
      ? transcripts.partialTranscript
      : null
  return {
    partialTranscript,
    finalTranscripts,
  }
}

const transcriptCreatedSince = (transcript: TranscriptionResult, now: number, since: number): boolean => {
  const createdAt = new Date(transcript.createdAt).getTime()
  const difference = (now - createdAt) / 1000
  return difference < since
}

export default transcriptSlice.reducer
