import {fromJS} from 'immutable'

import formatMessage from '@instructure/quiz-common/lib/format-message'
import ItemAnalysis from '../ItemAnalysis'
import { generateFormats } from '../../components/SDKApp'

describe('Item Analysis Record', () => {
  formatMessage.setup({formats: generateFormats('America/Denver')})

  const itemAnalysis = new ItemAnalysis(fromJS({
    itemId: '0',
    itemAnalysis: {
      scoreInfo: {
        resultCount: 5,
        resultSum: 10,
        scoreStddevPop: 2.5
      },
      correctAnswerInfo: {
        appearedCount: 5,
        resultCount: 2,
        resultSum: 10
      },
      incorrectAnswerInfo: {
        appearedCount: 5,
        resultCount: 1,
        resultSum: 0
      },
      topCorrectAnswerInfo: {
        appearedCount: 4,
        resultCount: 1,
        resultSum: 10
      },
      bottomCorrectAnswerInfo: {
        appearedCount: 1,
        resultCount: 0,
        resultSum: 0
      },
      unansweredInfo: 0,
      choiceInfo: [
        {
          itemBody: 'Monday',
          id: '1',
          choiceCount: 0
        },
        {
          itemBody: 'Tuesday',
          id: '2',
          choiceCount: 2
        },
        {
          itemBody: 'Wednesday',
          id: '3',
          choiceCount: 3
        }
      ],
      quintile: [1, 1, 2, 3, 5]
    }
  }))

  describe('Score Information', () => {
    it('returns scoreInfo', () => {
      expect(itemAnalysis.scoreInfo().get('resultCount')).to.be.equal(5)
      expect(itemAnalysis.scoreInfo().get('resultSum')).to.be.equal(10)
    })

    it('calculates mean score', () => {
      expect(itemAnalysis.meanScore()).to.be.equal('2.00')
    })
  })

  describe('Diffculty Information', () => {
    it('returns correctAnswerInfo', () => {
      expect(itemAnalysis.correctAnswerInfo().get('appearedCount')).to.be.equal(5)
      expect(itemAnalysis.correctAnswerInfo().get('resultCount')).to.be.equal(2)
    })

    it('calculates difficulty index', () => {
      expect(itemAnalysis.difficultyIndex()).to.be.equal('0.40')
    })
  })

  describe('Unanswered Information', () => {
    const unanswerableAnalysis = new ItemAnalysis(fromJS({
      itemAnalysis: {
        unansweredInfo: 4,
        choiceInfo: [{ itemBody: 'Pizza', choiceCount: 1 }, { itemBody: 'Tacos', choiceCount: 2 }]
      }
    }))

    it('returns unansweredInfo', () => {
      expect(unanswerableAnalysis.unansweredInfo()).to.eq(4)
    })

    it('is included in choice counts', () => {
      expect(unanswerableAnalysis.choiceCountMax()).to.eq(4)
      expect(unanswerableAnalysis.choiceCountSum()).to.eq(7)
    })
  })

  describe('Discrimination Information', () => {
    it('returns difficultyInfo for top scorers', () => {
      expect(itemAnalysis.topCorrectAnswerInfo().get('appearedCount')).to.be.equal(4)
      expect(itemAnalysis.topCorrectAnswerInfo().get('resultCount')).to.be.equal(1)
    })

    it('returns difficultyInfo for bottom scorers', () => {
      expect(itemAnalysis.bottomCorrectAnswerInfo().get('appearedCount')).to.be.equal(1)
      expect(itemAnalysis.bottomCorrectAnswerInfo().get('resultCount')).to.be.equal(0)
    })

    it('calculates discrimination index', () => {
      expect(itemAnalysis.discriminationIndex()).to.be.equal('0.25')
    })

    it('returns null if discrimination index cannot be calculated', () => {
      const newItemAnalysis = new ItemAnalysis(fromJS({
        itemAnalysis: {
          topCorrectAnswerInfo: {
            appearedCount: 1,
            resultCount: 1,
            resultSum: 10
          }
        }
      }))
      expect(newItemAnalysis.discriminationIndex()).to.be.equal(null)
    })
  })

  describe('Point BiSerial Correlation Coefficient', () => {
    it('calculates PBS', () => {
      expect(itemAnalysis.pointBiserial()).to.be.equal('0.57')
    })

    it('returns null if there are no incorrect answers', () => {
      const newItemAnalysis = itemAnalysis.setIn(['itemAnalysis', 'incorrectAnswerInfo', 'resultCount'], 0)
      expect(newItemAnalysis.pointBiserial()).to.be.equal(null)
    })

    it('returns null if standard deviation is 0', () => {
      const newItemAnalysis = itemAnalysis.setIn(['itemAnalysis', 'scoreInfo', 'scoreStddevPop'], 0)
      expect(newItemAnalysis.pointBiserial()).to.be.equal(null)
    })
  })

  describe('Choice Information', () => {
    it('returns choiceInfo', () => {
      expect(itemAnalysis.choiceInfo().toJS().length).to.be.equal(3)
    })

    it('calculates highest choice count', () => {
      expect(itemAnalysis.choiceCountMax()).to.be.equal(3)
    })

    it('calculates the sum of choice counts', () => {
      expect(itemAnalysis.choiceCountSum()).to.be.equal(5)
    })
  })

  describe('Calculated Metrics', () => {
    it('calculates the difficulty index', () => {
      expect(itemAnalysis.difficultyIndex()).to.be.equal('0.40')
    })
  })

  describe('Quintile Distribution', () => {
    it('returns quintile', () => {
      expect(itemAnalysis.quintile()).to.eql([1, 1, 2, 3, 5])
    })

    it('defaults to empty quintile', () => {
      const itemAnalysis = new ItemAnalysis(fromJS({ itemId: '0', itemAnalysis: {} }))
      expect(itemAnalysis.quintile()).to.eql([0, 0, 0, 0, 0])
    })
  })
})
