import ReactTestUtils from 'react-dom/test-utils'
import { fromJS } from 'immutable'

import QuizEntryEditFooter from '../presenter'
import Item from '../../../../../../../common/records/Item'
import QuizEntry from '../../../../../../../common/records/QuizEntry'
import styles from '../styles.css'
import { ITEM_FEEDBACK_MODAL } from '@instructure/quiz-common/lib/constants'

describe('QuizEntryEditFooter', () => {
  const sandbox = sinon.createSandbox()

  const alternativeRightFooterStub = sandbox.stub()
  const changeQuizEntryPointsStub = sandbox.stub()
  const clearChangesStub = sandbox.stub()
  const clearModificationsStub = sandbox.stub()
  const openModalStub = sandbox.stub()
  const setUiStub = sandbox.stub()
  const successfulSubmitStub = sandbox.stub()

  const workingQuizEntry = new QuizEntry({
    id: '55',
    pointsPossible: 3999
  })
  workingQuizEntry.isValid = () => true

  const quizEntry = new QuizEntry({
    id: '55',
    entryType: 'Item',
    entryId: 66,
    pointsPossible: 12,
    position: 3
  })

  const workingItem = new Item({
    id: '1',
    properties: {
      varyPointsByAnswer: false
    }
  })
  workingItem.isValid = () => true
  workingItem.getErrors = () => fromJS({})
  workingItem.errorsFor = () => fromJS({})

  const item = new Item({ id: '66' })

  const defaultProps = {
    changeQuizEntryPoints: changeQuizEntryPointsStub,
    clearChanges: clearChangesStub,
    clearModifications: clearModificationsStub,
    displayPosition: 1,
    entry: item,
    guid: 'guid123',
    isValid: true,
    openModal: openModalStub,
    quizEntry,
    quizId: '99',
    setUi: setUiStub,
    successfulSubmit: successfulSubmitStub,
    workingEntry: workingItem,
    workingQuizEntry
  }

  const testbed = createTestbed(withContext(QuizEntryEditFooter), defaultProps)

  beforeEach(() => {
    sandbox.resetHistory()
  })

  shouldRenderComponent(
    testbed, {}, QuizEntryEditFooter
  )

  describe('item feedback', () => {
    it('calls open item feedback modal', () => {
      const item2 = new Item(fromJS({
        feedback: { neutral: 'neutral' }
      }))

      testbed.render({ entry: item2 })
      const feedbackButton = testbed.findChildrenByClass(styles.feedbackSection)[0].childNodes[0]
      ReactTestUtils.Simulate.click(feedbackButton)

      expect(setUiStub.called).to.be.true()
      expect(openModalStub).to.be.calledOnce.calledWith(ITEM_FEEDBACK_MODAL,
        sinon.match.has('modalTrigger'))
    })
  })

  context('points section', () => {
    it('displays the points possible', () => {
      testbed.render()
      expect(testbed.rootNode.innerHTML.match(/3,999/)).to.exist()
    })

    it('is disabled when varyPointsByAnswer is true', () => {
      const workingItem2 = new Item({
        id: '1',
        properties: {
          varyPointsByAnswer: true
        },
        scoringData: {
          values: [{
            value: 'someId',
            points: 3
          }, {
            value: 'otherId',
            points: 5
          }]
        }
      })
      testbed.render({workingEntry: workingItem2})
      const input = testbed.findChildByTagName('input')
      expect(input.disabled).to.be.true()
    })

    it('is not disabled when varyPointsByAnswer is false', () => {
      testbed.render()
      const input = testbed.findChildByTagName('input')
      expect(input.disabled).to.be.false()
    })

    it('renders regradeAdjustedPointsPossible when present', () => {
      const regradedQuizEntry = new QuizEntry({
        id: '55',
        entryType: 'Item',
        entryId: 66,
        pointsPossible: 12,
        position: 3,
        regradeAdjustedPointsPossible: 15
      })
      testbed.render({workingQuizEntry: regradedQuizEntry})
      const input = testbed.findChildrenByTagName('input')[0]
      expect(input.value).to.equal('15')
    })

    it('calls changeQuizEntryPoints on change', () => {
      testbed.render()
      const input = testbed.findChildrenByTagName('input')[0]
      testbed.change(input, '456')
      expect(changeQuizEntryPointsStub).to.have.been.calledWith(quizEntry.id, 456)
    })

    it('resets to zero on blur with invalid input', () => {
      testbed.render()
      const input = testbed.findChildrenByTagName('input')[0]
      testbed.change(input, 'thisisnotanumber')
      ReactTestUtils.Simulate.blur(input)
      expect(input.value).to.equal('0')
    })

    it('does not reset to zero on blur valid input', () => {
      testbed.render()
      const input = testbed.findChildrenByTagName('input')[0]
      ReactTestUtils.Simulate.blur(input)
      expect(input.value).to.equal('3,999')
    })
  })

  describe('alternativeRightFooter', () => {
    it('does not render save/cancel buttons', () => {
      testbed.render({alternativeRightFooter: alternativeRightFooterStub})
      const buttonTexts = testbed.findChildrenByTagName('button').map(b => b.innerText)
      expect(buttonTexts).to.not.include('Cancel')
      expect(buttonTexts).to.not.include('Done')
    })

    it('calls the alternativeRightFooter', () => {
      testbed.render({alternativeRightFooter: alternativeRightFooterStub})
      expect(alternativeRightFooterStub).to.have.been.calledOnce()
    })

    it('renders the content returned by alternativeRightFooter', () => {
      testbed.render({alternativeRightFooter: () => 'alternativeRightFooterContent'})
      expect(testbed.getText()).to.contain('alternativeRightFooterContent')
    })
  })

  context('cancelling', () => {
    it('clears modifications', () => {
      testbed.render()
      const buttons = testbed.findChildrenByTagName('button')
      const cancelButton = buttons.find(b => b.innerText === 'Cancel')
      ReactTestUtils.Simulate.click(cancelButton)
      expect(clearChangesStub).to.be.calledOnce()
    })
  })

  context('submitting', () => {
    it('updates existing quiz entry and item', () => {
      testbed.render()
      const buttons = testbed.findChildrenByTagName('button')
      const doneButton = buttons.find(b => b.innerText === 'Done')
      ReactTestUtils.Simulate.click(doneButton)
      expect(successfulSubmitStub).to.be.calledOnce()
    })
  })

  describe('a11y tests', () => {
    it('should meet a11y standards', (done) => {
      testbed.render()
      testbed.checkA11yStandards(done, { ignores: ['label', 'label-title-only'] })
    })
  })
})
