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

import Progress from '@instructure/ui-elements/lib/components/Progress'
import Alert from '@instructure/ui-alerts/lib/components/Alert'

import QuizSession from '../../../../../records/QuizSession'
import QuizSessionResult from '../../../../../records/QuizSessionResult'
import QuizSessionResultInfo from '../index'

import FormattedDuration from '../../../../shared/FormattedDuration'

import styles from '../styles.css'

describe('QSRInfo', () => {
  const quizSession = new QuizSession({elapsedTime: 3600})
  const quizSessionResult = new QuizSessionResult({
    sessionItemResults: List(),
    score: 9,
    pointsPossible: 10,
    percentage: 0.9
  })
  const sessionItemResults = fromJS([
    { scoredData: { gradeStatus: 'graded' } },
    { scoredData: { gradeStatus: 'waiting' } },
    { scoredData: { gradeStatus: 'waiting' } }
  ])
  const testbed = createTestbed(QuizSessionResultInfo, {
    lang: 'en',
    quizSessionResult,
    quizSession,
    sessionItemResults
  })

  describe('score display', () => {
    context('unknown value', () => {
      const resultWithoutScore = new QuizSessionResult({
        pointsPossible: 10
      })

      const resultWithoutPointsPossible = new QuizSessionResult({
        score: 10
      })

      it('is hidden if score is unknown', () => {
        testbed.render({
          quizSessionResult: resultWithoutScore
        })
        const progressComponent = testbed.findChildrenByType(Progress)[0]
        expect(progressComponent).to.be.undefined()
      })

      it('is hidden if points possible is unknown', () => {
        testbed.render({
          quizSessionResult: resultWithoutPointsPossible
        })
        const progressComponent = testbed.findChildrenByType(Progress)[0]
        expect(progressComponent).to.be.undefined()
      })
    })

    context('known value', () => {
      const resultWithPercentage = new QuizSessionResult({
        score: 1,
        pointsPossible: 2,
        percentage: 0.5
      })

      it('shows their percentage as a float', () => {
        testbed.render({
          quizSessionResult: resultWithPercentage
        })
        const progressComponent = testbed.findChildByType(Progress)
        const progressText = ReactDOM.findDOMNode(progressComponent).textContent
        expect(progressText).to.include('50%')
      })

      it('shows the percentage as a float in the in the aria-valuetext', () => {
        testbed.render({
          quizSessionResult: resultWithPercentage
        })
        const tag = ReactDOM.findDOMNode(testbed.findChildByTagName('progress'))
        const ariaText = tag.getAttribute('aria-valuetext')
        expect(ariaText).to.include('Your score was 50%.')
      })
    })
  })

  describe('ungraded question alert', () => {
    const quizSessionWith3Items = quizSession.merge({
      sessionItems: fromJS([{position: 1}, {position: 2}, {position: 3}])
    })
    const quizSessionResultWith1Result = quizSessionResult.merge({
      sessionItemResults: fromJS([{position: 1}]),
      id: '2'
    })

    it('renders an Alert if there are ungraded questions', () => {
      testbed.render({
        quizSessionResult: quizSessionResultWith1Result,
        quizSession: quizSessionWith3Items
      })

      const alertComponent = testbed.findChildrenByType(Alert)[0]
      expect(alertComponent).to.not.be.undefined()
    })

    it('shows the number of questions needing grading', () => {
      testbed.render({
        quizSessionResult: quizSessionResultWith1Result,
        quizSession: quizSessionWith3Items
      })

      expect(testbed.getText()).to.include('2 questions require grading')
    })

    it('does not render an alert if all questions have been graded', () => {
      const quizSessionResultWith3Results = quizSessionResult.merge({
        sessionItemResults: fromJS([{position: 1}, {position: 2}, {position: 3}]),
        id: '2'
      })
      const sessionItemResults = fromJS([
        {score: 0}, {score: 1}, {score: 2}
      ])
      testbed.render({
        quizSessionResult: quizSessionResultWith3Results,
        quizSession: quizSessionWith3Items,
        sessionItemResults: sessionItemResults
      })

      const alertComponent = testbed.findChildrenByType(Alert)[0]
      expect(alertComponent).to.be.undefined()
    })
  })

  describe('render tests', () => {
    context('points display', () => {
      context('score and points possible present', () => {
        it('should display score', () => {
          testbed.render()
          const pointsElem = testbed.findChildrenByClass(styles.info_wrapper)[0]
          expect(testbed.getText(pointsElem)).to.include('9')
        })

        it('should display points possible', () => {
          testbed.render()
          const pointsElem = testbed.findChildrenByClass(styles.info_wrapper)[0]
          expect(testbed.getText(pointsElem)).to.include('Out of 10 points')
        })

        it('should display percentage', () => {
          testbed.render()
          const percentageElem = testbed.findChildrenByClass(styles.score_percentage)[0]
          expect(testbed.getText(percentageElem)).to.include(90)
        })
      })

      context('only score present', () => {
        const resultWithOnlyScore = new QuizSessionResult({
          score: 9
        })

        it('should only display score', () => {
          testbed.render({
            quizSessionResult: resultWithOnlyScore
          })
          const pointsElem = testbed.findChildrenByClass(styles.info_wrapper)[0]
          expect(testbed.getText(pointsElem)).to.include('9 Earned points')
        })

        it('should not display percentage', () => {
          testbed.render({
            quizSessionResult: resultWithOnlyScore
          })
          const percentageElem = testbed.findChildrenByClass(styles.score_percentage)[0]
          expect(percentageElem).to.be.undefined()
        })
      })

      context('only points possible present', () => {
        const resultWithOnlyPointsPossible = new QuizSessionResult({
          pointsPossible: 10
        })

        it('should only display points possible', () => {
          testbed.render({
            quizSessionResult: resultWithOnlyPointsPossible
          })
          const pointsElem = testbed.findChildrenByClass(styles.info_wrapper)[0]
          expect(testbed.getText(pointsElem)).to.include('10 Points possible')
        })

        it('should not display percentage', () => {
          testbed.render({
            quizSessionResult: resultWithOnlyPointsPossible
          })
          const percentageElem = testbed.findChildrenByClass(styles.score_percentage)[0]
          expect(percentageElem).to.be.undefined()
        })
      })

      context('only points possible present', () => {
        const resultWithNoPointsValues = new QuizSessionResult()

        it('should display a points placeholder', () => {
          testbed.render({
            quizSessionResult: resultWithNoPointsValues
          })
          const pointsElem = testbed.findChildrenByClass(styles.info_wrapper)[0]
          expect(testbed.getText(pointsElem)).to.include('-- Points possible')
        })

        it('should not display percentage', () => {
          testbed.render({
            quizSessionResult: resultWithNoPointsValues
          })
          const percentageElem = testbed.findChildrenByClass(styles.score_percentage)[0]
          expect(percentageElem).to.be.undefined()
        })
      })
    })

    context('elapsed time display', () => {
      it('should display time', () => {
        testbed.render()
        const formattedTime = testbed.findChildrenByType(FormattedDuration)[0]
        expect(formattedTime.props.timeLimitInSeconds).to.eq(3600)
      })

      it('should display Time for this attempt', () => {
        testbed.render()
        const percentageElem = testbed.findChildrenByClass(styles.info_wrapper)[1]
        expect(testbed.getText(percentageElem)).to.include('Time for this attempt')
      })
    })
  })

  describe('a11y tests', () => {
    it('should meet a11y standards', (done) => {
      testbed.render({})
      testbed.checkA11yStandards(done)
    })
  })
})
