"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.getCategoryRequest = exports.fetchCategories = void 0;
var _lodash = require("lodash");
var _mlRandomSamplerUtils = require("@kbn/ml-random-sampler-utils");
var _constants = require("../../../common/constants");
var _create_category_request = require("../../../common/api/log_categorization/create_category_request");
var _is_request_aborted_error = require("../../lib/is_request_aborted_error");
var _get_query_with_params = require("./get_query_with_params");
/*
 * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
 * or more contributor license agreements. Licensed under the Elastic License
 * 2.0; you may not use this file except in compliance with the Elastic License
 * 2.0.
 */

const getCategoryRequest = (params, fieldName, from, to, filter, {
  wrap
}) => {
  const {
    index,
    timeFieldName
  } = params;
  const query = (0, _get_query_with_params.getQueryWithParams)({
    params,
    termFilters: undefined,
    filter
  });
  const {
    params: request
  } = (0, _create_category_request.createCategoryRequest)(index, fieldName, timeFieldName, from, to, query, wrap);
  return request;
};
exports.getCategoryRequest = getCategoryRequest;
const fetchCategories = async (esClient, params, fieldNames, from, to, filter, logger,
// The default value of 1 means no sampling will be used
sampleProbability = 1, emitError, abortSignal) => {
  const randomSamplerWrapper = (0, _mlRandomSamplerUtils.createRandomSamplerWrapper)({
    probability: sampleProbability,
    seed: _constants.RANDOM_SAMPLER_SEED
  });
  const result = [];
  const settledPromises = await Promise.allSettled(fieldNames.map(fieldName => {
    const request = getCategoryRequest(params, fieldName, from, to, filter, randomSamplerWrapper);
    return esClient.search(request, {
      signal: abortSignal,
      maxRetries: 0
    });
  }));
  function reportError(fieldName, error) {
    if (!(0, _is_request_aborted_error.isRequestAbortedError)(error)) {
      logger.error(`Failed to fetch category aggregation for fieldName "${fieldName}", got: \n${JSON.stringify(error, null, 2)}`);
      emitError(`Failed to fetch category aggregation for fieldName "${fieldName}".`);
    }
  }
  for (const [index, settledPromise] of settledPromises.entries()) {
    const fieldName = fieldNames[index];
    if (settledPromise.status === 'rejected') {
      reportError(fieldName, settledPromise.reason);
      // Still continue the analysis even if individual category queries fail.
      continue;
    }
    const resp = settledPromise.value;
    const {
      aggregations
    } = resp;
    if (aggregations === undefined) {
      reportError(fieldName, resp);
      // Still continue the analysis even if individual category queries fail.
      continue;
    }
    const sparkLinesPerCategory = {};
    const {
      categories: {
        buckets
      }
    } = randomSamplerWrapper.unwrap(aggregations);
    const categories = buckets.map(b => {
      sparkLinesPerCategory[b.key] = b.sparkline === undefined ? {} : b.sparkline.buckets.reduce((acc2, cur2) => {
        acc2[cur2.key] = cur2.doc_count;
        return acc2;
      }, {});
      return {
        key: b.key,
        count: b.doc_count,
        examples: b.hit.hits.hits.map(h => (0, _lodash.get)(h._source, fieldName))
      };
    });
    result.push({
      categories,
      sparkLinesPerCategory
    });
  }
  return result;
};
exports.fetchCategories = fetchCategories;