import { Map, fromJS } from 'immutable'
import { expect } from 'chai'

import takingReducer from '../taking'
import {
  backtrackingNextQuestion,
  editResponse,
  loadResumeData,
  previousQuestion,
  sessionStartOrResumeEvent,
  setCurrentSessionItemPosition,
  updateIsTaking,
  updateQuizSessionStatusOnPageLoad,
  updateTimerInfo,
  updateTimerMinimized,
  updateQuizSubmitFlag
} from '../../actions/taking'
import { newActiveQuizSession } from '../../actions/quizSessions'
import { PENDING, IN_PROGRESS } from '@instructure/quiz-common/lib/constants'

import SessionItem from '../../records/SessionItem'

const sessionItem = new SessionItem({
  position: 1,
  item: { id: '1' },
  currentSessionItemPosition: 1
})

describe('taking Reducer', () => {
  context('sessionIdForCurrentItem equal to payload', () => {
    it('ACTIVE_QUIZ_SESSION_CHANGE does not change taking state', () => {
      const initialState = fromJS({
        currentSessionItemPosition: 3,
        sessionIdForCurrentItem: 7
      })
      const action = newActiveQuizSession(7)
      expect(takingReducer(initialState, action)).to.eq(initialState)
    })
  })

  context('sessionIdForCurrentItem not equal to payload', () => {
    it('ACTIVE_QUIZ_SESSION_CHANGE clears taking state', () => {
      const initialState = fromJS({
        currentSessionItemPosition: 3,
        sessionIdForCurrentItem: 5
      })
      const action = newActiveQuizSession(7)
      expect(takingReducer(initialState, action).isEmpty()).to.be.true()
    })
  })

  it('handles UPDATE_TIMER_MINIMIZED', () => {
    const initialState = fromJS({
      timerData: { timerMinimized: false }
    })
    const action = updateTimerMinimized(true)
    expect(takingReducer(initialState, action).getIn(['timerData', 'timerMinimized']))
      .to.be.true()
  })

  it('handles UPDATE_TIMER_MINIMIZED', () => {
    const initialState = Map({})
    const action = updateQuizSubmitFlag(true)
    expect(takingReducer(initialState, action).get('submitFlag')).to.be.true()
  })

  it('handles UPDATE_QUIZ_SESSION_STATUS_ON_PAGE_LOAD', () => {
    const initialState = fromJS({
      quizSessionStatusOnPageLoad: PENDING
    })
    const action = updateQuizSessionStatusOnPageLoad(IN_PROGRESS)
    expect(takingReducer(initialState, action).get('quizSessionStatusOnPageLoad'))
      .to.eq(IN_PROGRESS)
  })

  it('handles PREVIOUS_QUESTION', () => {
    const initialState = fromJS({ currentSessionItemPosition: 3 })
    const action = previousQuestion()
    expect(takingReducer(initialState, action).get('currentSessionItemPosition'))
      .to.eq(2)
  })

  it('handles BACKTRACKING_NEXT_QUESTION', () => {
    const initialState = fromJS({ currentSessionItemPosition: 3 })
    const action = backtrackingNextQuestion()
    expect(takingReducer(initialState, action).get('currentSessionItemPosition'))
      .to.eq(4)
  })

  it('handles SET_CURRENT_SESSION_ITEM_POSITION', () => {
    const initialState = fromJS({ currentSessionItemPosition: 3 })
    const action = setCurrentSessionItemPosition(20)
    expect(takingReducer(initialState, action).get('currentSessionItemPosition'))
      .to.eq(20)
  })

  it('handles UPDATE_IS_TAKING', () => {
    const initialState = Map({})
    const action = updateIsTaking(true)
    const nextState = takingReducer(initialState, action)

    expect(nextState.get('isTaking')).to.be.true()
  })

  it('handles UPDATE_TIMER_INFO', () => {
    const initialState = Map({})
    const action = updateTimerInfo(
      {
        timerRunning: true,
        timeLeftInSeconds: 3,
        timeRecording: false
      }
    )
    const nextState = takingReducer(initialState, action)

    expect(nextState.get('timerData').toJS()).to.eql(
      {
        timerRunning: true,
        timeLeftInSeconds: 3,
        timeRecording: false
      })
  })

  // testrail test_id: C2954596, C2954597
  it('handles SESSION_STARTED_OR_RESUMED_EVENT', () => {
    const initialState = Map({})
    const action = sessionStartOrResumeEvent('userAgent')
    const nextState = takingReducer(initialState, action)

    expect(nextState.get('browserSessionId')).to.have.lengthOf(36)
  })

  it('should add response with RESPONSE action if none exists', () => {
    const initialState = Map({})
    const action = editResponse(sessionItem, 'some arbitrary value')
    const nextState = takingReducer(initialState, action)
    const nextValue = nextState.getIn(['responses', 1]).get('userResponse')

    expect(nextValue.toJS()).to.deep.equal({ value: 'some arbitrary value' })
  })

  it('should replace a response value with RESPONSE action if response exists', () => {
    const initialState = fromJS({
      1: { userResponse: 'initial val' }
    })

    const action = editResponse(sessionItem, 'a new val')
    const nextState = takingReducer(initialState, action)
    const nextValue = nextState.getIn(['responses', 1]).get('userResponse')

    expect(nextValue.toJS()).to.deep.equal({ value: 'a new val' })
  })

  it('should add multiple responses when loading resume data', () => {
    const initialState = Map({})
    const respOne = {
      position: 1,
      userResponse: 'hey',
      itemId: '1'
    }
    const respTwo = {
      position: 2,
      userResponse: 'hello',
      itemId: '2'
    }
    const loadResumeAction = loadResumeData([respOne, respTwo])
    const nextState = takingReducer(initialState, loadResumeAction)
    const nextValue = nextState.getIn(['responses', 2]).get('userResponse')

    expect(nextValue).to.equal('hello')
  })

  it('returns the original state with bad action', () => {
    const initialState = Map({ foo: 'bar' })
    const action = Map({ type: 'something else' })
    const nextState = takingReducer(initialState, action)

    expect(nextState).to.equal(initialState)
  })
})
