// Licensed to the Apache Software Foundation (ASF) under one or more contributor
// license agreements; and to You under the Apache License, Version 2.0.

'use strict'

const test = require('ava')
const Client = require('../../lib/client')
const http = require('http')
const ProxyAgent = require('proxy-agent')

test('should use default constructor options', t => {
  const client = new Client({api_key: 'aaa', apihost: 'my_host'})
  t.false(client.options.ignoreCerts)
  t.is(client.options.apiKey, 'aaa')
  t.is(client.options.apiVersion, 'v1')
  t.is(client.options.api, 'https://my_host/api/v1/')
  t.falsy(client.options.namespace)
  t.falsy(client.options.cert)
  t.falsy(client.options.key)
})

test('should support explicit constructor options', t => {
  const client = new Client({
    namespace: 'ns',
    ignore_certs: true,
    api_key: 'aaa',
    api: 'my_host',
    apiversion: 'v2',
    apigw_token: 'oauth_token',
    apigw_space_guid: 'space_guid',
    cert: 'mycert=',
    key: 'mykey='
  })
  t.is(client.options.api, 'my_host')
  t.is(client.options.apiVersion, 'v2')
  t.true(client.options.ignoreCerts)
  t.is(client.options.namespace, 'ns')
  t.is(client.options.apigwToken, 'oauth_token')
  t.is(client.options.apigwSpaceGuid, 'space_guid')
  t.is(client.options.cert, 'mycert=')
  t.is(client.options.key, 'mykey=')
})

test('apihost and apiversion set', t => {
  const client = new Client({
    api_key: 'aaa',
    apihost: 'https://my_host',
    apiversion: 'v2'
  })
  t.is(client.options.api, 'https://my_host/api/v2/')
  t.is(client.options.apiVersion, 'v2')
})

test('should support deprecated explicit constructor options', t => {
  const client = new Client({
    namespace: 'ns',
    ignore_certs: true,
    api_key: 'aaa',
    api: 'my_host',
    apigw_token: 'oauth_token',
    apigw_space_guid: 'space_guid'
  })
  t.is(client.options.api, 'my_host')
  t.true(client.options.ignoreCerts)
  t.is(client.options.namespace, 'ns')
  t.is(client.options.apigwToken, 'oauth_token')
  t.is(client.options.apigwSpaceGuid, 'space_guid')
})

test('should use uuid from auth key as space guid if apigw_token present', t => {
  const client = new Client({
    namespace: 'ns',
    ignore_certs: true,
    api_key: 'uuid:pass',
    api: 'my_host',
    apigw_token: 'oauth_token'
  })
  t.is(client.options.apigwSpaceGuid, 'uuid')
})

test('should use environment parameters for options if not set explicitly.', t => {
  process.env['__OW_API_KEY'] = 'some_user:some_pass'
  process.env['__OW_API_HOST'] = 'mywhiskhost'
  process.env['__OW_IGNORE_CERTS'] = 'true'
  process.env['__OW_APIGW_TOKEN'] = 'my-token'
  process.env['__OW_APIGW_SPACE_GUID'] = 'my-space'
  const client = new Client()
  t.is(client.options.apiKey, process.env['__OW_API_KEY'])
  t.is(client.options.api, 'https://mywhiskhost/api/v1/')
  t.is(client.options.ignoreCerts, true)
  t.is(client.options.apigwToken, 'my-token')
  t.is(client.options.apigwSpaceGuid, 'my-space')
  delete process.env['__OW_API_KEY']
  delete process.env['__OW_API_HOST']
  delete process.env['__OW_IGNORE_CERTS']
  delete process.env['__OW_APIGW_TOKEN']
  delete process.env['__OW_APIGW_SPACE_GUID']
})

test('should use options for parameters even if environment parameters are available.', t => {
  process.env['__OW_API_KEY'] = 'some_user:some_pass'
  process.env['__OW_API_HOST'] = 'mywhiskhost'
  process.env['__OW_APIGW_TOKEN'] = 'my-token'
  process.env['__OW_APIGW_SPACE_GUID'] = 'my-space'
  const client = new Client({apihost: 'openwhisk', api_key: 'mykey', apigw_token: 'token', apigw_space_guid: 'guid'})
  t.is(client.options.apiKey, 'mykey')
  t.is(client.options.api, 'https://openwhisk/api/v1/')
  t.is(client.options.apigwToken, 'token')
  t.is(client.options.apigwSpaceGuid, 'guid')
  delete process.env['__OW_API_KEY']
  delete process.env['__OW_API_HOST']
  delete process.env['__OW_APIGW_TOKEN']
  delete process.env['__OW_APIGW_SPACE_GUID']
})

test('should throw error when missing API key option.', t => {
  t.throws(() => new Client({api: true}), /Missing api_key parameter./)
})

test('should throw error when missing both API and API Host options.', t => {
  t.throws(() => new Client({api_key: true}), /Missing either api or apihost parameters/)
})

test('should handle multiple api parameter formats', t => {
  const client = new Client({api_key: true, apihost: 'blah'})
  t.is(client.urlFromApihost('my_host'), 'https://my_host/api/v1/')
  t.is(client.urlFromApihost('https://my_host:80'), 'https://my_host:80/api/v1/')
  t.is(client.urlFromApihost('http://my_host:80'), 'http://my_host:80/api/v1/')
})

test('should return default request parameters without options', async t => {
  const client = new Client({api_key: 'username:password', apihost: 'blah'})
  const METHOD = 'get'
  const PATH = 'some/path/to/resource'

  const params = await client.params(METHOD, PATH)
  t.is(params.url, 'https://blah/api/v1/some/path/to/resource')
  t.is(params.method, METHOD)
  t.true(params.json)
  t.true(params.rejectUnauthorized)
  t.true(params.headers.hasOwnProperty('Authorization'))
  t.falsy(params.cert)
  t.falsy(params.key)
})

test('should return request parameters with merged options', async t => {
  const client = new Client({api_key: 'username:password', apihost: 'blah'})
  const METHOD = 'get'
  const PATH = 'some/path/to/resource'
  const OPTIONS = {b: {bar: 'foo'}, a: {foo: 'bar'}}

  const params = await client.params(METHOD, PATH, OPTIONS)
  t.is(params.url, 'https://blah/api/v1/some/path/to/resource')
  t.is(params.method, METHOD)
  t.true(params.json)
  t.true(params.rejectUnauthorized)
  t.true(params.headers.hasOwnProperty('Authorization'))
  t.deepEqual(params.a, {foo: 'bar'})
  t.deepEqual(params.b, {bar: 'foo'})
})

test('should return request parameters with cert and key client options', async t => {
  const client = new Client({api_key: 'username:password', apihost: 'blah', cert: 'mycert=', key: 'mykey='})
  const METHOD = 'get'
  const PATH = 'some/path/to/resource'
  const OPTIONS = { myoption: true }

  const params = await client.params(METHOD, PATH, OPTIONS)
  t.is(params.url, 'https://blah/api/v1/some/path/to/resource')
  t.is(params.method, METHOD)
  t.is(params.cert, 'mycert=')
  t.is(params.key, 'mykey=')
})

test('should be able to use proxy options leveraging the proxy agent.', async t => {
  process.env['proxy'] = 'http://some_proxy'
  const client = new Client({api_key: 'username:password', apihost: 'blah'})
  const METHOD = 'get'
  const PATH = 'some/path/to/resource'
  const OPTIONS = {agent: new ProxyAgent(process.env['proxy'])}

  const params = await client.params(METHOD, PATH, OPTIONS)
  t.is(params.method, METHOD)
  t.true(params.json)
  t.true(params.rejectUnauthorized)
  t.true(params.headers.hasOwnProperty('Authorization'))
  t.deepEqual(params.agent.proxyUri, 'http://some_proxy')
  delete process.env['proxy']
})

test('should return request parameters with explicit api option', async t => {
  const client = new Client({api_key: 'username:password', api: 'https://api.com/api/v1'})
  const METHOD = 'get'
  const PATH = 'some/path/to/resource'

  t.is((await client.params(METHOD, PATH)).url, 'https://api.com/api/v1/some/path/to/resource')
  client.options.api += '/'
  t.is((await client.params(METHOD, PATH)).url, 'https://api.com/api/v1/some/path/to/resource')
})

test('should generate auth header from API key', async t => {
  const apiKey = 'some sample api key'
  const client = new Client({api: true, api_key: apiKey})
  t.is(await client.authHeader(), `Basic ${Buffer.from(apiKey).toString('base64')}`)
})

test('should generate auth header from 3rd party authHandler plugin', async t => {
  const authHandler = {
    getAuthHeader: () => {
      return Promise.resolve('Basic user:password')
    }
  }
  const client = new Client({api: true, auth_handler: authHandler})
  t.is(await client.authHeader(), `Basic user:password`)
})

test('should return path and status code in error message', t => {
  const client = new Client({api_key: true, api: true})
  const method = 'METHOD'
  const url = 'https://blah.com/api/v1/actions/list'
  const statusCode = 400
  t.throws(() => client.handleErrors({
    options: {method, url},
    statusCode
  }), `${method} ${url} Returned HTTP ${statusCode} (${http.STATUS_CODES[statusCode]}) --> "Response Missing Error Message."`)
})

test('should return response error string in error message', t => {
  const client = new Client({api_key: true, api: true})
  const method = 'METHOD'
  const url = 'https://blah.com/api/v1/actions/list'
  const statusCode = 400
  t.throws(() => client.handleErrors({
    error: {error: 'hello'},
    options: {method, url},
    statusCode
  }), `${method} ${url} Returned HTTP ${statusCode} (${http.STATUS_CODES[statusCode]}) --> "hello"`)
  t.throws(() => client.handleErrors({
    error: {response: {result: {error: 'hello'}}},
    options: {method, url},
    statusCode
  }), `${method} ${url} Returned HTTP ${statusCode} (${http.STATUS_CODES[statusCode]}) --> "hello"`)
  t.throws(() => client.handleErrors({
    error: {response: {result: {error: {error: 'hello'}}}},
    options: {method, url},
    statusCode
  }), `${method} ${url} Returned HTTP ${statusCode} (${http.STATUS_CODES[statusCode]}) --> "hello"`)
  t.throws(() => client.handleErrors({
    error: {response: {result: {error: {statusCode: 404}}}},
    options: {method, url},
    statusCode
  }), `${method} ${url} Returned HTTP ${statusCode} (${http.STATUS_CODES[statusCode]}) --> "application error, status code: ${404}"`)
})

test('should throw errors for non-HTTP response failures', t => {
  const client = new Client({api_key: true, api: true})
  t.throws(() => client.handleErrors({message: 'error message'}), /error message/)
})

test('should contain x-namespace-id header when namespace in contructor options', async t => {
  const authHandler = {
    getAuthHeader: () => {
      return Promise.resolve('Bearer access_token')
    }
  }
  const client = new Client({apihost: 'my_host', namespace: 'ns', auth_handler: authHandler})
  const METHOD = 'POST'
  const PATH = '/publicnamespace/path/to/resource'
  let params = await client.params(METHOD, PATH, {})
  t.is(client.options.namespace, 'ns')
  t.is(params.headers['x-namespace-id'], client.options.namespace)
})

test('should not contain x-namespace-id header when namespace is not in contructor options', async t => {
  const authHandler = {
    getAuthHeader: () => {
      return Promise.resolve('Bearer access_token')
    }
  }
  const client = new Client({apihost: 'my_host', auth_handler: authHandler})
  const METHOD = 'POST'
  const PATH = '/publicnamespace/path/to/resource'
  let params = await client.params(METHOD, PATH, {})
  t.is(params.headers['x-namespace-id'], undefined)
})
