"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.getAgentStatusById = getAgentStatusById;
exports.getAgentStatusForAgentPolicy = getAgentStatusForAgentPolicy;
exports.getIncomingDataByAgentsId = getIncomingDataByAgentsId;
var _esQuery = require("@kbn/es-query");
var _services = require("../../../common/services");
var _constants = require("../../constants");
var _errors = require("../../errors");
var _app_context = require("../app_context");
var _crud = require("./crud");
var _build_status_runtime_field = require("./build_status_runtime_field");
/*
 * 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 DATA_STREAM_INDEX_PATTERN = 'logs-*-*,metrics-*-*,traces-*-*,synthetics-*-*';
const MAX_AGENT_DATA_PREVIEW_SIZE = 20;
async function getAgentStatusById(esClient, soClient, agentId) {
  return (await (0, _crud.getAgentById)(esClient, soClient, agentId)).status;
}
async function getAgentStatusForAgentPolicy(esClient, soClient, agentPolicyId, filterKuery) {
  var _response, _response$aggregation, _response$aggregation2;
  const logger = _app_context.appContextService.getLogger();
  const runtimeFields = await (0, _build_status_runtime_field.buildAgentStatusRuntimeField)(soClient);
  const clauses = [];
  if (filterKuery) {
    const kueryAsElasticsearchQuery = (0, _esQuery.toElasticsearchQuery)((0, _esQuery.fromKueryExpression)((0, _crud.removeSOAttributes)(filterKuery)));
    clauses.push(kueryAsElasticsearchQuery);
  }
  if (agentPolicyId) {
    clauses.push({
      term: {
        policy_id: agentPolicyId
      }
    });
  }
  const query = clauses.length > 0 ? {
    bool: {
      must: clauses
    }
  } : undefined;
  const statuses = {
    online: 0,
    error: 0,
    inactive: 0,
    offline: 0,
    updating: 0,
    unenrolled: 0,
    degraded: 0,
    enrolling: 0,
    unenrolling: 0
  };
  let response;
  try {
    response = await esClient.search({
      index: _constants.AGENTS_INDEX,
      size: 0,
      query,
      fields: Object.keys(runtimeFields),
      runtime_mappings: runtimeFields,
      aggregations: {
        status: {
          terms: {
            field: 'status',
            size: Object.keys(statuses).length
          }
        }
      },
      ignore_unavailable: true
    });
  } catch (error) {
    logger.debug(`Error getting agent statuses: ${error}`);
    throw error;
  }
  const buckets = ((_response = response) === null || _response === void 0 ? void 0 : (_response$aggregation = _response.aggregations) === null || _response$aggregation === void 0 ? void 0 : (_response$aggregation2 = _response$aggregation.status) === null || _response$aggregation2 === void 0 ? void 0 : _response$aggregation2.buckets) || [];
  buckets.forEach(bucket => {
    if (statuses[bucket.key] !== undefined) {
      statuses[bucket.key] = bucket.doc_count;
    }
  });
  const {
    healthy: online,
    unhealthy: error,
    ...otherStatuses
  } = (0, _services.agentStatusesToSummary)(statuses);
  const combinedStatuses = {
    online,
    error,
    ...otherStatuses
  };
  const allStatuses = Object.values(statuses).reduce((acc, val) => acc + val, 0);
  const allActive = allStatuses - combinedStatuses.unenrolled - combinedStatuses.inactive;
  return {
    ...combinedStatuses,
    /* @deprecated no agents will have other status */
    other: 0,
    /* @deprecated Agent events do not exists anymore */
    events: 0,
    /* @deprecated use active instead */
    total: allActive,
    all: allStatuses,
    active: allActive
  };
}
async function getIncomingDataByAgentsId(esClient, agentsIds, returnDataPreview = false) {
  try {
    var _searchResult$aggrega, _searchResult$hits;
    const {
      has_all_requested: hasAllPrivileges
    } = await esClient.security.hasPrivileges({
      body: {
        index: [{
          names: [DATA_STREAM_INDEX_PATTERN],
          privileges: ['read']
        }]
      }
    });
    if (!hasAllPrivileges) {
      throw new _errors.FleetUnauthorizedError('Missing permissions to read data streams indices');
    }
    const searchResult = await esClient.search({
      index: DATA_STREAM_INDEX_PATTERN,
      allow_partial_search_results: true,
      _source: returnDataPreview,
      timeout: '5s',
      size: returnDataPreview ? MAX_AGENT_DATA_PREVIEW_SIZE : 0,
      body: {
        query: {
          bool: {
            filter: [{
              terms: {
                'agent.id': agentsIds
              }
            }, {
              range: {
                '@timestamp': {
                  gte: 'now-5m',
                  lte: 'now'
                }
              }
            }]
          }
        },
        aggs: {
          agent_ids: {
            terms: {
              field: 'agent.id',
              size: agentsIds.length
            }
          }
        }
      }
    });
    if (!((_searchResult$aggrega = searchResult.aggregations) !== null && _searchResult$aggrega !== void 0 && _searchResult$aggrega.agent_ids)) {
      return {
        items: agentsIds.map(id => {
          return {
            items: {
              [id]: {
                data: false
              }
            }
          };
        }),
        data: []
      };
    }

    // @ts-expect-error aggregation type is not specified
    const agentIdsWithData = searchResult.aggregations.agent_ids.buckets.map(bucket => bucket.key);
    const dataPreview = ((_searchResult$hits = searchResult.hits) === null || _searchResult$hits === void 0 ? void 0 : _searchResult$hits.hits) || [];
    const items = agentsIds.map(id => agentIdsWithData.includes(id) ? {
      [id]: {
        data: true
      }
    } : {
      [id]: {
        data: false
      }
    });
    return {
      items,
      dataPreview
    };
  } catch (e) {
    throw new Error(e);
  }
}