/* global cy, Cypress */

const { extend, get, merge, find } = Cypress._;

export function createDashboard(name) {
  return cy.request("POST", "api/dashboards", { name }).then(({ body }) => body);
}

export function createQuery(data, shouldPublish = true) {
  const merged = extend(
    {
      name: "Test Query",
      query: "select 1",
      data_source_id: 1,
      options: {
        parameters: [],
      },
      schedule: null,
    },
    data
  );

  // eslint-disable-next-line cypress/no-assigning-return-values
  let request = cy.request("POST", "/api/queries", merged).then(({ body }) => body);
  if (shouldPublish) {
    request = request.then(query =>
      cy.request("POST", `/api/queries/${query.id}`, { is_draft: false }).then(() => query)
    );
  }

  return request;
}

export function createVisualization(queryId, type, name, options) {
  const data = { query_id: queryId, type, name, options };
  return cy.request("POST", "/api/visualizations", data).then(({ body }) => ({
    query_id: queryId,
    ...body,
  }));
}

export function addTextbox(dashboardId, text = "text", options = {}) {
  const defaultOptions = {
    position: { col: 0, row: 0, sizeX: 3, sizeY: 3 },
  };

  const data = {
    width: 1,
    dashboard_id: dashboardId,
    visualization_id: null,
    text,
    options: merge(defaultOptions, options),
  };

  return cy.request("POST", "api/widgets", data).then(({ body }) => {
    const id = get(body, "id");
    assert.isDefined(id, "Widget api call returns widget id");
    return body;
  });
}

export function addWidget(dashboardId, visualizationId, options = {}) {
  const defaultOptions = {
    position: { col: 0, row: 0, sizeX: 3, sizeY: 3 },
  };

  const data = {
    width: 1,
    dashboard_id: dashboardId,
    visualization_id: visualizationId,
    options: merge(defaultOptions, options),
  };

  return cy.request("POST", "api/widgets", data).then(({ body }) => {
    const id = get(body, "id");
    assert.isDefined(id, "Widget api call returns widget id");
    return body;
  });
}

export function createAlert(queryId, options = {}, name) {
  const defaultOptions = {
    column: "?column?",
    op: "greater than",
    rearm: 0,
    value: 1,
  };

  const data = {
    query_id: queryId,
    name: name || "Alert for query " + queryId,
    options: merge(defaultOptions, options),
  };

  return cy.request("POST", "api/alerts", data).then(({ body }) => {
    const id = get(body, "id");
    assert.isDefined(id, "Alert api call returns alert id");
    return body;
  });
}

export function createUser({ name, email, password }) {
  return cy
    .request({
      method: "POST",
      url: "api/users",
      body: { name, email },
      failOnStatusCode: false,
    })
    .then(xhr => {
      const { status, body } = xhr;
      if (status < 200 || status > 400) {
        throw new Error(xhr);
      }

      if (status === 400 && body.message === "Email already taken.") {
        // all is good, do nothing
        return;
      }

      const id = get(body, "id");
      assert.isDefined(id, "User api call returns user id");

      return cy.request({
        url: body.invite_link,
        method: "POST",
        form: true,
        body: { password },
      });
    });
}

export function createDestination(name, type, options = {}) {
  return cy.request({
    method: "POST",
    url: "api/destinations",
    body: { name, type, options },
    failOnStatusCode: false,
  });
}

export function getDestinations() {
  return cy.request("GET", "api/destinations").then(({ body }) => body);
}

export function addDestinationSubscription(alertId, destinationName) {
  return getDestinations()
    .then(destinations => {
      const destination = find(destinations, { name: destinationName });
      if (!destination) {
        throw new Error("Destination not found");
      }
      return cy.request("POST", `api/alerts/${alertId}/subscriptions`, {
        alert_id: alertId,
        destination_id: destination.id,
      });
    })
    .then(({ body }) => {
      const id = get(body, "id");
      assert.isDefined(id, "Subscription api call returns subscription id");
      return body;
    });
}
