import { AUTH_TOKEN } from '../commands';
import {
  createGuestUserRequest,
  GuestDetails,
  GuestDetailsShortForEmail,
  GuestDetailsShortForName
} from '@support-user/index';
import { HttpRequest, HttpStatusCodes } from '../base';
import Ajv from 'ajv';

Cypress.Commands.add('createGuest', (guestDetails: GuestDetails) => {
  cy.allure().logStep('Initiate create guest flow');
  createGuest(guestDetails);
});

Cypress.Commands.add('createGuestByEmail', (guestDetails: GuestDetailsShortForEmail) => {
  const { email, age = 30, gender = 'MALE', travelerType = 'Business' } = guestDetails;
  cy.allure().logStep('Initiate create guest flow');
  createGuest({
    email,
    age,
    gender,
    travelerType
  });
});

Cypress.Commands.add('createGuestByName', (guestInfoByName: GuestDetailsShortForName) => {
  const {
    givenName,
    familyName,
    age = 30,
    gender = 'MALE',
    travelerType = 'Business'
  } = guestInfoByName;
  cy.allure().logStep('Initiate create guest flow');
  createGuest({
    givenName,
    familyName,
    age,
    gender,
    travelerType
  });
});

Cypress.Commands.add('validateSchema', (schema: any, data: any) => {
  return cy.wrap(validateSchema(schema, data));
});

Cypress.Commands.add('getCurrentUserInfo', () => {
  cy.allure().logStep('fetch current user info');
  getUserInfo();
});

function createGuest(guestDetails: GuestDetails) {
  if (AUTH_TOKEN) {
    cy.request({
      method: 'POST',
      url: '/api/user/guests',
      headers: {
        Authorization: AUTH_TOKEN
      },
      body: createGuestUserRequest(guestDetails),
      retryOnStatusCodeFailure: true
    }).then(({ status }) => {
      expect(status, 'Created guest user').to.equal(200);
    });
  } else {
    throw new Error('Please login before calling api endpoints');
  }
}

function validateSchema(schema: any, data: any) {
  const ajv = new Ajv({ allErrors: true });
  const validate = ajv.compile(schema);
  cy.log('Debug|Validate: Result: ', validate(data));
  const valid = validate(data);
  if (valid) {
    cy.log('SCHEMA is VALID!!!');
  } else {
    cy.log(ajv.errorsText(validate.errors));
    console.log(ajv.errorsText(validate.errors));
    cy.log('SCHEMA is INVALID!');
  }
  return valid;
}

function getUserInfo() {
  if (AUTH_TOKEN) {
    cy.request({
      method: HttpRequest.Get,
      url: `/api/uaa/userinfo`,
      headers: {
        Authorization: AUTH_TOKEN
      },
      retryOnStatusCodeFailure: true
    }).then(({ body, status }) => {
      expect(status, 'Fetch User Info ').to.equal(HttpStatusCodes.Ok);
      cy.task('putDataInCache', {
        key: 'userInfo',
        data: body
      });
    });
  } else {
    throw new Error('Please login before calling api endpoints');
  }
}
