import {
  FILE_UPLOAD_CALL
} from '@instructure/quiz-common/lib/constants'

import Fetcher from '../../util/Fetcher'

import {
  startCallFor,
  successCallFor
} from '../../util/callHelpers'

import {jsoniblePromise} from '../../util/jsonify'
import makeFakeFetch from '../../../../tests/util/fakeFetch'

import {
  getUploadUrl,
  sendFileToS3
} from '../fileUpload'

describe('fileUpload', () => {
  // reset in useFakeFetching
  const dispatchStub = sinon.stub()
  const getStateStub = sinon.stub()
  const fetchStub = sinon.stub()

  useFakeFetching({dispatchStub, getStateStub, fetchStub})

  const onErrorStub = sinon.stub()
  const onSuccessStub = sinon.stub()

  afterEach(() => {
    onErrorStub.resetHistory()
    onSuccessStub.resetHistory()
  })

  describe('sendFileToS3', () => {
    const fakeS3Url = 'http://s3/fake/url'
    const fakeQueryString = '?query_string'
    const uploadUrlResponse = { url: fakeS3Url + fakeQueryString }
    const dummyFile = { type: 'filetype', name: 'BLOB' }

    const errorResponse = jsoniblePromise({status: 500})
    const fakeErrorFetch = makeFakeFetch(errorResponse)
    const emptyResponse = jsoniblePromise({})
    const fakeEmptyFetch = makeFakeFetch(emptyResponse)

    const fakeSendFileToS3 = (file = dummyFile) => {
      const sendFileToS3Thunk = sendFileToS3(file, onErrorStub, onSuccessStub, dispatchStub, getStateStub)
      return sendFileToS3Thunk(uploadUrlResponse)
    }

    it('should mark the file upload url fetch call as started', () => {
      fakeSendFileToS3()
      checkActionDispatched(dispatchStub, startCallFor(FILE_UPLOAD_CALL))
    })

    it('should upload to the provided url', () => {
      fakeSendFileToS3()
      expect(fetchStub.calledWith(uploadUrlResponse.url)).to.be.true()
    })

    it('should remove the query string', (done) => {
      Fetcher.fakeFetch = fakeEmptyFetch

      fakeSendFileToS3().then(() => {
        done()
        expect(onSuccessStub.calledWith(fakeS3Url)).to.be.true()
      })
    })

    it('should mark the create call as a success on return', (done) => {
      Fetcher.fakeFetch = fakeEmptyFetch

      fakeSendFileToS3().then(() => {
        checkActionDispatched(dispatchStub, successCallFor(FILE_UPLOAD_CALL))
        done()
      })
    })

    it('supports unicode filenames', () => {
      fakeSendFileToS3({ type: 'txt', name: '𐌱𐍂𐌹𐌲𐌲𐌹𐌸 '})
      expect(fetchStub.calledOnce).to.be.true()
    })

    context('error on uploading the file', () => {
      it('should call the onError callback', (done) => {
        Fetcher.fakeFetch = fakeErrorFetch

        fakeSendFileToS3().then(done())

        expect(onErrorStub.called).to.be.true()
      })
    })
  })

  describe('getUploadUrl', () => {
    it('calls to the proper url', () => {
      Fetcher.fakeFetch = fetchStub
      getUploadUrl('foo.com')

      expect(fetchStub.calledWith('foo.com')).to.be.true()
    })
  })
})
