import configureStore from 'redux-mock-store'
import thunkMiddleware from 'redux-thunk'
import multi from 'redux-multi'

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

import {
  addTagAssociation,
  removePendingAdditionTagAssociation,
  removePendingDeletionTagAssociation,
  removeTagAssociation,
  setTagSuggestions
} from '../../../common/actions/tagAssociations'

import {
  createTagAssociations,
  deleteTagAssociations,
  getTagSuggestions
} from '../tagAssociations'

describe('tag associations api actions', () => {
  const tagAssociation = {
    id: '2',
    tag_id: '2',
    tag_value: 'quiz'
  }

  useFakeFetching()

  const mockStore = configureStore([multi, thunkMiddleware])

  describe('createTagAssociations', () => {
    const createFetch = makeFakeFetch(jsoniblePromise(tagAssociation))

    beforeEach(() => {
      Fetcher.fakeFetch = createFetch
    })

    afterEach(() => {
      createFetch.resetHistory()
    })

    it('should hit the right endpoint', () => {
      const store = mockStore()
      store.dispatch(createTagAssociations('1', 'Item', '2', ['quiz']))
      expect(createFetch).to.have.been.calledWith('/api/bank_entries/1/tag_associations')
    })

    it('should trigger additional actions', async () => {
      const store = mockStore()
      await store.dispatch(createTagAssociations('1', 'Item', '2', ['quiz']))
      const addAction = addTagAssociation('Item', '2', tagAssociation)
      expect(store.getActions()).to.deep.include(addAction)
      const removePendingAction = removePendingAdditionTagAssociation('Item', '2', 'quiz')
      expect(store.getActions()).to.deep.include(removePendingAction)
    })
  })

  describe('deleteTagAssociations', () => {
    const deleteFetch = makeFakeFetch(jsoniblePromise())

    beforeEach(() => {
      Fetcher.fakeFetch = deleteFetch
    })

    afterEach(() => {
      deleteFetch.resetHistory()
    })

    it('should hit the right endpoint', () => {
      const store = mockStore()
      store.dispatch(deleteTagAssociations('1', 'Item', '2', ['3']))
      expect(deleteFetch).to.have.been.calledWith('/api/bank_entries/1/tag_associations/3')
    })

    it('should trigger additional actions', async () => {
      const store = mockStore()
      await store.dispatch(deleteTagAssociations('1', 'Item', '2', ['3']))
      const removeAction = removeTagAssociation('Item', '2', '3')
      expect(store.getActions()).to.deep.include(removeAction)
      const removePendingAction = removePendingDeletionTagAssociation('Item', '2', '3')
      expect(store.getActions()).to.deep.include(removePendingAction)
    })
  })

  describe('getTagSuggestions', () => {
    const getFetch = makeFakeFetch(jsoniblePromise([tagAssociation]))

    beforeEach(() => {
      Fetcher.fakeFetch = getFetch
    })

    afterEach(() => {
      getFetch.resetHistory()
    })

    it('should hit the right endpoint', () => {
      const store = mockStore()
      store.dispatch(getTagSuggestions('Item', '2', 'qu'))
      expect(getFetch).to.have.been.calledWith('/api/tags?filter=qu')
    })

    it('should encode special characters properly', () => {
      const store = mockStore()
      store.dispatch(getTagSuggestions('Item', '2', '?'))
      expect(getFetch).to.have.been.calledWith('/api/tags?filter=%3F')
    })

    it('should trigger additional actions', async () => {
      const store = mockStore()
      await store.dispatch(getTagSuggestions('Item', '2', 'tags'))
      const action = setTagSuggestions('Item', '2', [tagAssociation], 'tags')
      expect(store.getActions()).to.deep.include(action)
    })
  })
})
