/**
 * Copyright (c) HashiCorp, Inc.
 * SPDX-License-Identifier: BUSL-1.1
 */

const not = `(n't| not)?`;
export default function (scenario, assert, lastNthRequest) {
  // lastNthRequest should return a
  // {
  //   method: '',
  //   requestBody: '',
  //   requestHeaders: ''
  // }
  scenario
    .then('the last $method requests included from yaml\n$yaml', function (method, data) {
      const requests = lastNthRequest(null, method);
      const a = new Set(data);
      const b = new Set(
        requests.map(function (item) {
          return item.url;
        })
      );
      const diff = new Set(
        [...a].filter(function (item) {
          return !b.has(item);
        })
      );
      assert.equal(diff.size, 0, `Expected requests "${[...diff].join(', ')}"`);
    })
    .then(`a $method request was${not} made to "$endpoint"`, function (method, negative, url) {
      const isNegative = typeof negative !== 'undefined';
      const requests = lastNthRequest(null, method);
      const request = requests.some(function (item) {
        return method === item.method && url === item.url;
      });
      if (isNegative) {
        assert.notOk(request, `Didn't expect a ${method} request url to ${url}`);
      } else {
        assert.ok(request, `Expected a ${method} request url to ${url}`);
      }
    })
    .then('a $method request was made to "$endpoint" with no body', function (method, url) {
      const requests = lastNthRequest(null, method);
      const request = requests.find(function (item) {
        return method === item.method && url === item.url;
      });
      assert.equal(
        request.requestBody,
        null,
        `Expected the request body to be null, was ${request.requestBody}`
      );
    })
    .then(
      'a $method request was made to "$endpoint" with the body "$body"',
      function (method, url, body) {
        const requests = lastNthRequest(null, method);
        const request = requests.find(function (item) {
          return method === item.method && url === item.url;
        });
        assert.ok(request, `Expected a ${method} request url to ${url} with the body "${body}"`);
      }
    )
    .then(
      'a $method request was made to "$endpoint" from yaml\n$yaml',
      function (method, url, yaml) {
        const requests = lastNthRequest(null, method);
        const request = requests.find(function (item) {
          return method === item.method && url === item.url;
        });
        let data = yaml.body || {};
        const body = JSON.parse(request.requestBody);
        Object.keys(data).forEach(function (key, i, arr) {
          assert.deepEqual(
            body[key],
            data[key],
            `Expected the payload to contain ${key} equaling ${JSON.stringify(
              data[key]
            )}, ${key} was ${JSON.stringify(body[key])}`
          );
        });
        data = yaml.headers || {};
        const headers = request.requestHeaders;
        Object.keys(data).forEach(function (key, i, arr) {
          assert.deepEqual(
            headers[key],
            data[key],
            `Expected the payload to contain ${key} equaling ${JSON.stringify(
              data[key]
            )}, ${key} was ${JSON.stringify(headers[key])}`
          );
        });
      }
    )
    .then(
      'a $method request was made to "$endpoint" without properties from yaml\n$yaml',
      function (method, url, properties) {
        const requests = lastNthRequest(null, method);
        const request = requests.find(function (item) {
          return method === item.method && url === item.url;
        });
        const body = JSON.parse(request.requestBody);
        properties.forEach(function (key, i, arr) {
          assert.equal(
            typeof body[key],
            'undefined',
            `Expected payload to not have a ${key} property`
          );
        });
      }
    );
}
