// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

import { validateResponseBodies, generateEasyAuthHeader, graphQLEndPoint, statusCodes, validateStatusCode, validateNoErrorsInResponse, validateStatusCodes } from '../Helper.js';
import http from 'k6/http';
import { check } from 'k6';

// This test performs create operations through GraphQL and REST
// on the same entity in parallel and validates the responses
// In the chosen entity, the primary keys are auto-generated
// Response status codes and bodies are validated
export const validateParallelCreateOperationsWhenPrimaryKeyIsAutogenerated = () => {

  let headers = generateEasyAuthHeader('authenticated');

  const parameters = {
    headers: headers
  }

  let createPublisher = `mutation createPublisher($item: CreatePublisherInput!){
    createPublisher(item: $item) {
      id
      name
    }
  }`;

  let createPublisherVariable = {
    "item": {
      "name": "Office Publisher"
    }
  };

  let createPublisherRestUrl = "https://localhost:5001/api/Publisher/";

  let createPublisherRestRequestBody = `{
    "name": "Office Publisher"
  }`;

  // Each REST or GraphQL request is created as a named request. Named requests are useful
  // for validating the responses.
  const queryNames = ['createPublisherUsingGraphQL', 'createPublisherUsingRest'];

  const expectedStatusCodes = {
    'createPublisherUsingGraphQL': statusCodes.Ok,
    'createPublisherUsingRest': statusCodes.Created
  };

  const expectedResponse1 = {
    'createPublisherUsingRest': {
      "value": [
        {
          "id": 5001,
          "name": "Office Publisher"
        }
      ]
    },
    'createPublisherUsingGraphQL': {
      "data": {
        "createPublisher": {
          "id": 5002,
          "name": "Office Publisher"
        }
      }
    }

  };

  const expectedResponse2 = {
    'createPublisherUsingRest': {
      "value": [
        {
          "id": 5002,
          "name": "Office Publisher"
        }
      ]
    },
    'createPublisherUsingGraphQL': {
      "data": {
        "createPublisher": {
          "id": 5001,
          "name": "Office Publisher"
        }
      }
    }

  };

  const requests = {
    'createPublisherUsingGraphQL': {
      method: 'POST',
      url: graphQLEndPoint,
      body: JSON.stringify({ query: createPublisher, variables: createPublisherVariable }),
      params: parameters
    },
    'createPublisherUsingRest': {
      method: 'POST',
      url: createPublisherRestUrl,
      body: createPublisherRestRequestBody,
      params: parameters
    }
  };

  // Performs all the GraphQL and REST requests in parallel
  const responses = http.batch(requests);

  // Validations for the API responses
  check(responses, {
    'Validate no errors': validateNoErrorsInResponse(queryNames, responses),
    'Validate expected status code': validateStatusCode(queryNames, responses, expectedStatusCodes),
    'Validate API response': validateResponseBodies(queryNames, responses, expectedResponse1, expectedResponse2)
  });

};

// This test performs create operations through REST on the same item in parallel
// In the chosen entity, the primary keys are not auto-generated. So, only one of the
// create operations is expected to be successful
// Response status codes are validated
export const valdiateParallelCreateOperationsWherePrimaryKeyIsNotAutogenerated = () => {
  let headers = generateEasyAuthHeader('authenticated');

  const parameters = {
    headers: headers
  }

  let createBrokerRestUrl = "https://localhost:5001/api/Broker/";

  let createBrokerRestRequestBody1 = `{
    "ID Number": 3,
    "First Name": "Shyam",
    "Last Name": "Sundar"
  }`;

  let createBrokerRestRequestBody2 = `{
    "ID Number": 3,
    "First Name": "Ayush",
    "Last Name": "Agarawal"
  }`;

  // Each REST or GraphQL request is created as a named request. Named requests are useful
  // for validating the responses.
  const queryNames = ['createBroker1', 'createBroker2'];

  const requests = {
    'createBroker1': {
      method: 'POST',
      url: createBrokerRestUrl,
      body: createBrokerRestRequestBody1,
      params: parameters
    },
    'createBroker2': {
      method: 'POST',
      url: createBrokerRestUrl,
      body: createBrokerRestRequestBody2,
      params: parameters
    }
  };

  // Both the operations attempts to create an item with the same id. In the Broker entity, the primary
  // key is not auto-generated
  // Both the requests should not be successful as that would result in primary key constraint violation
  // Hence, the expectation that one of the requests should fail
  const expectedStatusCodes1 = {
    'createBroker1': statusCodes.Created,
    'createBroker2': statusCodes.InternalServerError
  };

  const expectedStatusCodes2 = {
    'createBroker1': statusCodes.InternalServerError,
    'createBroker2': statusCodes.Created
  };

  // Performs all the GraphQL and REST requests in parallel
  const responses = http.batch(requests);

  //Validate status codes of the responses
  validateStatusCodes(queryNames, responses, expectedStatusCodes1, expectedStatusCodes2);
};
