import { fromJS, List } from 'immutable'
import ReactDOM from 'react-dom'

import Spinner from '../../../../../common/components/shared/spinner/Spinner'
import Quiz from '../../../../../common/records/Quiz'
import QuizAnalysis from '../../../../../common/records/QuizAnalysis'
import ItemAnalysis from '../../../../../common/records/ItemAnalysis'
import QuizAndItemAnalysis from '../presenter'
import withContext from '../../../../../../tests/util/withContext'
import MetricsListItem from '../../../MetricsListItem'

describe('QuizAndItemAnalysis', () => {
  const activeQuizId = '1'
  const getItemAnalysesStub = sinon.stub()
  const getQuizAnalysisStub = sinon.stub()
  const getExistingQuizStub = sinon.stub()
  const toggleItemAnalysisRowExpandedStub = sinon.stub()
  const quiz = new Quiz({id: activeQuizId, title: 'Test Quiz'})

  const itemAnalysis1 = new ItemAnalysis(fromJS({
    itemId: '3',
    itemBody: 'This is the item body',
    itemAnalysis: {
      scoreInfo: {
        resultSum: 3,
        resultCount: 1,
        scoreStddevPop: 1.2
      },
      correctAnswerInfo: {
        resultSum: 50,
        resultCount: 8,
        appearedCount: 20
      },
      topCorrectAnswerInfo: {
        resultCount: 8,
        appearedCount: 20
      },
      bottomCorrectAnswerInfo: {
        resultCount: 2,
        appearedCount: 20
      },
      incorrectAnswerInfo: {
        resultSum: 5,
        resultCount: 8
      },
      unansweredInfo: 1,
      difficultyInfo: {
        responseCount: 8,
        correctAnswerCount: 1
      },
      choiceInfo: [
        {
          choiceCount: 2,
          id: 'id',
          itemBody: '<p>Item&gt;Body</p>',
          correct: true
        },
        {
          choiceCount: 3,
          id: 'not_id',
          itemBody: 'choice Item Body not correct',
          correct: false
        },
        {
          choiceCount: 4,
          id: 'not_id_again',
          itemBody: 'choice Item Body not correct still',
          correct: false
        }
      ],
      quintile: [1, 2, 3, 4, 5]
    }
  }))

  const itemAnalysis2 = new ItemAnalysis(fromJS({
    itemId: '5',
    itemBody: 'This is another item body',
    itemAnalysis: {
      scoreInfo: {
        resultSum: 3,
        resultCount: 1,
        scoreStddevPop: 1.2
      },
      correctAnswerInfo: {
        resultSum: 50,
        resultCount: 8,
        appearedCount: 20
      },
      topCorrectAnswerInfo: {
        resultCount: 8,
        appearedCount: 20
      },
      bottomCorrectAnswerInfo: {
        resultCount: 2,
        appearedCount: 20
      },
      incorrectAnswerInfo: {
        resultSum: 5,
        resultCount: 8
      },
      unansweredInfo: 1,
      difficultyInfo: {
        responseCount: 8,
        correctAnswerCount: 1
      },
      choiceInfo: [
        {
          choiceCount: 2,
          id: 'id',
          itemBody: '<p>Item&gt;Body</p>',
          correct: true
        },
        {
          choiceCount: 3,
          id: 'not_id',
          itemBody: 'choice Item Body not correct',
          correct: false
        },
        {
          choiceCount: 4,
          id: 'not_id_again',
          itemBody: 'choice Item Body not correct still',
          correct: false
        }
      ],
      quintile: [1, 2, 1, 3, 4]
    }
  }))

  const quizAnalysis = new QuizAnalysis(fromJS({
    quizId: '1',
    quizAnalysis: {
      centile: Array.from({length: 101}, (v, i) => i/100),
      decile: Array.from({length: 10}, (v, i) => i),
      scoreInfo: {
        resultSum: 5,
        resultCount: 1,
        scoreMax: 100,
        scoreMin: 2,
        scoreSum: 1000,
        scoreCount: 40,
        pointsPossible: 100,
        scoreStddevPop: 20
      },
      cronbachsAlpha: 5
    },
    batchTimestamp: new Date('Thu Feb 07 2019 15:35:17 GMT-0500 (Eastern Standard Time)')
  }))

  quiz.getItemAnalyses = () => new List([itemAnalysis1, itemAnalysis2])
  quiz.getQuizAnalysis = () => quizAnalysis

  const QuizAndItemAnalysisWithContext = withContext(QuizAndItemAnalysis)

  const testbed = createTestbed(QuizAndItemAnalysisWithContext, {
    activeQuizId,
    getExistingQuiz: getExistingQuizStub,
    getItemAnalyses: getItemAnalysesStub,
    getQuizAnalysis: getQuizAnalysisStub,
    quiz,
    quizAnalysis,
    toggleItemAnalysisRowExpanded: toggleItemAnalysisRowExpandedStub
  })

  shouldRenderComponent(testbed, {}, QuizAndItemAnalysisWithContext)

  it('should render spinner if quiz has not loaded', () => {
    testbed.render({ quiz: new Quiz() })
    const spinner = testbed.findChildrenByType(Spinner)[0]

    expect(spinner).to.exist()
  })

  it('should render not found card if quiz analysis is not found', () => {
    testbed.render({quizAnalysisNotFound: true})
    expect(testbed.getText()).to.include('No reports yet')
  })

  it('should trigger reload of data if quizId changes', () => {
    testbed.render({})
    expect(getExistingQuizStub.calledWith('1')).to.be.true()
    testbed.render({activeQuizId: '2'})
    expect(getExistingQuizStub.calledWith('2')).to.be.true()
  })

  describe('Quiz and Item analysis metrics', () => {
    it('renders all metrics with none specified', () => {
      testbed.render({})
      const listItems = testbed.findChildrenByType(MetricsListItem)
      // 6 for the quiz, 4 for each item = 14
      expect(listItems.length).to.eq(14)
    })

    it('only shows requested item metrics, when requested', () => {
      testbed.render({
        itemMetrics: ['rpb', 'difficultyIndex']
      })
      const listItems = testbed.findChildrenByType(MetricsListItem)
      // 6 for the quiz, 2 for each item = 10
      expect(listItems.length).to.eq(10)
      listItems.forEach(item => {
        const label = ReactDOM.findDOMNode(item).innerText
        expect(label).not.to.contain('Discrimination Index')
        expect(label).not.to.contain('Mean Earned Score')
      })
    })

    it('only shows requested quiz metrics, when requested', () => {
      testbed.render({
        quizMetrics: ['highScore', 'lowScore', 'meanScore']
      })
      const listItems = testbed.findChildrenByType(MetricsListItem)
      // 3 for the quiz, 4 for each item = 11
      expect(listItems.length).to.eq(11)
      listItems.forEach(item => {
        const label = ReactDOM.findDOMNode(item).innerText
        expect(label).not.to.contain('Standard Deviation')
        expect(label).not.to.contain('Mean Elapsed Time')
        expect(label).not.to.contain('Cronbach\'s Alpha')
      })
    })
  })
})
