import { Credentials, config } from 'aws-sdk/global'
import Kinesis from 'aws-sdk/clients/kinesis'
import getKinesisConfig, {
  buildCredentials,
  buildKinesisClient,
  buildKinesisConfiguration
} from '../client'

describe('kinesis client helper', () => {
  const fakeCreds = {
    access_key_id: 'id',
    expiration: 4000,
    secret_access_key: 'secret',
    session_token: 'token'
  }

  const fakeConfiguration = {
    stream_identifiers: {
      events: 'hi',
      responses: 'bye'
    },
    server_time: Date.now()
  }

  const fakeResponse = {
    credentials: fakeCreds,
    ...fakeConfiguration
  }

  const credentials = buildCredentials(fakeCreds)

  describe('buildCredentials', () => {
    it('builds a credential', () => {
      expect(credentials).to.be.an.instanceof(Credentials)
      expect(credentials.expireTime).to.eq(Date.parse(fakeCreds.expiration))
    })
  })

  describe('buildKinesisConfiguration', () => {
    context('creates global aws offset', () => {
      it('works with client time > server time', () => {
        const fakeClock = sinon.useFakeTimers()
        const configWithOffset = Object.assign({}, fakeConfiguration, {server_time: new Date(Date.now() - 1000)})
        buildKinesisConfiguration({ configuration: configWithOffset, credentials })
        expect(config.systemClockOffset).to.eq(-1000)
        fakeClock.restore()
      })

      it('works with client time < server time', () => {
        const fakeClock = sinon.useFakeTimers()
        const configWithOffset = Object.assign({}, fakeConfiguration, {server_time: new Date(Date.now() + 1000)})
        buildKinesisConfiguration({ configuration: configWithOffset, credentials })
        expect(config.systemClockOffset).to.be.eq(1000)
        fakeClock.restore()
      })
    })

    const kinesisConfig = buildKinesisConfiguration({ configuration: fakeConfiguration, credentials })
    it('returns a kinesisClient', () => {
      expect(kinesisConfig.client).to.be.an.instanceof(Kinesis)
    })

    it('returns some streamConfigs', () => {
      expect(kinesisConfig.streamConfigs.length).to.equal(2)
    })
  })

  describe('buildKinesisClient', () => {
    const client = buildKinesisClient({}, credentials)
    it('builds a kinesis client', () => {
      expect(client).to.be.an.instanceof(Kinesis)
    })
  })

  describe('getKinesisConfig', () => {
    const fakeResolver = (value) => {
      return {
        then: function (callback) {
          callback(value)
        }
      }
    }
    const fakeFetcher = {
      post: sinon.stub().returns(fakeResolver(fakeResponse))
    }

    it('calls for credentials for new data', () => {
      getKinesisConfig('1', fakeFetcher)
      expect(fakeFetcher.post.called).to.be.true()
    })

    it('returns a kinesis client', (done) => {
      const responsePromise = getKinesisConfig('1', fakeFetcher)
      responsePromise.then((config) => {
        expect(config.client).to.be.an.instanceof(Kinesis)
        done()
      })
    })
  })
})
