import aiFeaturesReducer, {
  aiResultReceived,
  clearAIFeatures,
  initAIFeatures,
  initAIResults,
  setAIFeaturesError,
  setAIFeaturesStatus,
} from './aiFeatureSlice'
import { AIFeaturesModel, AIFeaturesStatus } from './models'
import { AIFeature, AIFeatureKind, AIFeatureType, AIResult, AIResultStatus } from '@zocks-communications/client-sdk-js'

const aiFeatures: AIFeature[] = [
  {
    id: '1',
    name: 'Family',
    type: AIFeatureType.TOPIC_DETECTION,
    kind: AIFeatureKind.CUSTOM,
    generalConfig: {
      multiUserInput: false,
      userLevel: true,
      retranscribe: false,
      lifecycle: {
        realtime: true,
        fullContext: false,
      },
      saveContext: false,
    },
    config: {
      topicMinimumConfidence: 0.5,
      topics: ['children', 'divorce', 'separation'],
    },
    executionTargets: [],
    resultTargets: [],
    metadata: '',
  },
  {
    id: '2',
    name: 'QA',
    type: AIFeatureType.QUESTION_ANSWER,
    kind: AIFeatureKind.CUSTOM,
    generalConfig: {
      multiUserInput: false,
      userLevel: true,
      retranscribe: false,
      lifecycle: {
        realtime: true,
        fullContext: false,
      },
      saveContext: false,
    },
    config: {
      questions: [{ id: 'test-question-id', question: 'Test question?', answerType: 'string' }],
      answerRoles: [],
      answerMinimumConfidence: 0.5,
    },
    executionTargets: [],
    resultTargets: [],
    metadata: '',
  },
]

const aiResults: AIResult[] = [
  {
    id: '1',
    aiFeatureId: '1',
    roomId: 'testRoomId',
    sessionId: 'testSessionId',
    status: AIResultStatus.PROCESSED,
    createdAt: '2023-02-08T12:49:20.212613Z',
    userId: 'myUserId',
    result: {
      type: AIFeatureType.TOPIC_DETECTION,
      detectedTopic: 'children',
      confidence: 0.9,
      context: 'My son.',
    },
    scores: [
      {
        userId: 'test-user-id',
        score: 5,
      },
    ],
  },
  {
    id: '2',
    aiFeatureId: '2',
    roomId: 'testRoomId',
    sessionId: 'testSessionId',
    status: AIResultStatus.PROCESSED,
    createdAt: '2023-02-08T12:49:20.212613Z',
    userId: 'myUserId',
    result: {
      type: AIFeatureType.QUESTION_ANSWER,
      questionId: 'test-question-id',
      answer: 'Test answer',
      confidence: 0.9,
      context: 'Test context.',
    },
    scores: [],
  },
]

test('handles init AI features', () => {
  const state: AIFeaturesModel = {
    aiFeaturesStatus: AIFeaturesStatus.INITIAL,
    aiFeatures: {},
    errors: [],
  }

  const newState = aiFeaturesReducer(state, initAIFeatures(aiFeatures))

  expect(newState).toStrictEqual({
    aiFeaturesStatus: 'success',
    errors: [],
    aiFeatures: {
      '1': {
        id: '1',
        name: 'Family',
        type: 'topicDetection',
        kind: 'custom',
        generalConfig: {
          lifecycle: {
            fullContext: false,
            realtime: true,
          },
          multiUserInput: false,
          retranscribe: false,
          saveContext: false,
          userLevel: true,
        },
        config: {
          topicMinimumConfidence: 0.5,
          topics: ['children', 'divorce', 'separation'],
        },
        results: [],
        resultTargets: [],
        executionTargets: [],
        metadata: '',
      },
      '2': {
        id: '2',
        name: 'QA',
        type: AIFeatureType.QUESTION_ANSWER,
        kind: 'custom',
        generalConfig: {
          lifecycle: {
            fullContext: false,
            realtime: true,
          },
          multiUserInput: false,
          retranscribe: false,
          saveContext: false,
          userLevel: true,
        },
        config: {
          questions: [{ id: 'test-question-id', question: 'Test question?', answerType: 'string' }],
          answerRoles: [],
          answerMinimumConfidence: 0.5,
        },
        executionTargets: [],
        resultTargets: [],
        metadata: '',
        results: [],
      },
    },
  })
})

test('handles init AI results', () => {
  const state: AIFeaturesModel = {
    aiFeaturesStatus: AIFeaturesStatus.INITIAL,
    aiFeatures: {},
    errors: [],
  }

  const newState = aiFeaturesReducer(state, initAIFeatures(aiFeatures))
  const stateWithAIResults = aiFeaturesReducer(newState, initAIResults(aiResults))

  expect(stateWithAIResults).toStrictEqual({
    aiFeaturesStatus: 'success',
    errors: [],
    aiFeatures: {
      '1': {
        id: '1',
        name: 'Family',
        type: 'topicDetection',
        kind: 'custom',
        generalConfig: {
          lifecycle: {
            fullContext: false,
            realtime: true,
          },
          multiUserInput: false,
          retranscribe: false,
          saveContext: false,
          userLevel: true,
        },
        config: {
          topicMinimumConfidence: 0.5,
          topics: ['children', 'divorce', 'separation'],
        },
        results: [
          {
            id: '1',
            aiFeatureId: '1',
            roomId: 'testRoomId',
            sessionId: 'testSessionId',
            status: 'processed',
            createdAt: '2023-02-08T12:49:20.212613Z',
            userId: 'myUserId',
            result: {
              type: AIFeatureType.TOPIC_DETECTION,
              detectedTopic: 'children',
              confidence: 0.9,
              context: 'My son.',
            },
            scores: [
              {
                userId: 'test-user-id',
                score: 5,
              },
            ],
          },
        ],
        resultTargets: [],
        executionTargets: [],
        metadata: '',
      },
      '2': {
        id: '2',
        name: 'QA',
        type: AIFeatureType.QUESTION_ANSWER,
        kind: 'custom',
        generalConfig: {
          lifecycle: {
            fullContext: false,
            realtime: true,
          },
          multiUserInput: false,
          retranscribe: false,
          saveContext: false,
          userLevel: true,
        },
        config: {
          questions: [{ id: 'test-question-id', question: 'Test question?', answerType: 'string' }],
          answerRoles: [],
          answerMinimumConfidence: 0.5,
        },
        executionTargets: [],
        resultTargets: [],
        metadata: '',
        results: [
          {
            id: '2',
            aiFeatureId: '2',
            roomId: 'testRoomId',
            sessionId: 'testSessionId',
            status: 'processed',
            createdAt: '2023-02-08T12:49:20.212613Z',
            userId: 'myUserId',
            result: {
              type: AIFeatureType.QUESTION_ANSWER,
              questionId: 'test-question-id',
              answer: 'Test answer',
              confidence: 0.9,
              context: 'Test context.',
            },
            scores: [],
          },
        ],
      },
    },
  })
})

test('handles clear AI features', () => {
  const state: AIFeaturesModel = {
    aiFeaturesStatus: AIFeaturesStatus.INITIAL,
    aiFeatures: { '1': { ...aiFeatures[0], results: [] } },
    errors: [],
  }

  const newState = aiFeaturesReducer(state, clearAIFeatures())

  expect(newState).toStrictEqual({
    aiFeaturesStatus: AIFeaturesStatus.IDLE,
    aiFeatures: {},
    errors: [],
  })
})

test('handles set AI features status', () => {
  const state: AIFeaturesModel = {
    aiFeaturesStatus: AIFeaturesStatus.INITIAL,
    aiFeatures: {},
    errors: [],
  }

  const newState = aiFeaturesReducer(state, setAIFeaturesStatus(AIFeaturesStatus.ERROR))

  expect(newState).toStrictEqual({
    aiFeaturesStatus: AIFeaturesStatus.ERROR,
    aiFeatures: {},
    errors: [],
  })
})

test('handles set AI features error', () => {
  const state: AIFeaturesModel = {
    aiFeaturesStatus: AIFeaturesStatus.INITIAL,
    aiFeatures: {},
    errors: [],
  }

  const newState = aiFeaturesReducer(state, setAIFeaturesError({ errors: [{ message: 'error' }] }))

  expect(newState).toStrictEqual({
    aiFeaturesStatus: AIFeaturesStatus.ERROR,
    aiFeatures: {},
    errors: [{ message: 'error' }],
  })
})

test('handles topic detection result received', () => {
  const state: AIFeaturesModel = {
    aiFeaturesStatus: AIFeaturesStatus.INITIAL,
    aiFeatures: { '1': { ...aiFeatures[0], results: [] } },
    errors: [],
  }

  const newState = aiFeaturesReducer(
    state,
    aiResultReceived({
      id: '1',
      result: {
        type: AIFeatureType.TOPIC_DETECTION,
        context: 'My son.',
        confidence: 0.9,
        detectedTopic: 'children',
      },
      aiFeatureId: '1',
      roomId: 'testRoomId',
      sessionId: 'testSessionId',
      status: AIResultStatus.PROCESSED,
      userId: '123',
      createdAt: '2023-02-08T12:49:20.212613Z',
      scores: [],
    })
  )

  expect(newState.aiFeatures['1'].results).toStrictEqual([
    {
      id: '1',
      result: {
        type: AIFeatureType.TOPIC_DETECTION,
        context: 'My son.',
        confidence: 0.9,
        detectedTopic: 'children',
      },
      aiFeatureId: '1',
      roomId: 'testRoomId',
      sessionId: 'testSessionId',
      status: 'processed',
      userId: '123',
      createdAt: '2023-02-08T12:49:20.212613Z',
      scores: [],
    },
  ])
})

test('handles topic detection result received with non-existent topic in the AI feature', () => {
  const state: AIFeaturesModel = {
    aiFeaturesStatus: AIFeaturesStatus.INITIAL,
    aiFeatures: { '1': { ...aiFeatures[0], results: [] } },
    errors: [],
  }

  const newState = aiFeaturesReducer(
    state,
    aiResultReceived({
      result: {
        type: AIFeatureType.TOPIC_DETECTION,
        context: 'My son.',
        confidence: 0.9,
        detectedTopic: 'non existent topic',
      },
      aiFeatureId: '1',
      id: '1',
      roomId: 'testRoomId',
      sessionId: 'testSessionId',
      status: AIResultStatus.PROCESSED,
      userId: '123',
      createdAt: '2023-02-08T12:49:20.212613Z',
      scores: [],
    })
  )

  expect(newState.aiFeatures['1'].results).toEqual([])
})

test('handles topic detection result received with non-existent AI feature', () => {
  const state: AIFeaturesModel = {
    aiFeaturesStatus: AIFeaturesStatus.INITIAL,
    aiFeatures: { '1': { ...aiFeatures[0], results: [] } },
    errors: [],
  }

  const newState = aiFeaturesReducer(
    state,
    aiResultReceived({
      result: {
        type: AIFeatureType.TOPIC_DETECTION,
        context: 'My son.',
        confidence: 0.9,
        detectedTopic: 'children',
      },
      aiFeatureId: '2',
      id: '1',
      roomId: 'testRoomId',
      sessionId: 'testSessionId',
      status: AIResultStatus.PROCESSED,
      userId: '123',
      createdAt: '2023-02-08T12:49:20.212613Z',
      scores: [],
    })
  )

  expect(newState.aiFeatures['1'].results).toEqual([])
})
