"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.getActionsWithKuery = exports.getActionsByIds = exports.getActionResultsWithKuery = exports.getActionResultsByIds = exports.createAction = exports.bulkCreateActions = void 0;
var _uuid = require("uuid");
var _esQuery = require("@kbn/es-query");
var _constants = require("../../../common/constants");
var _errors = require("../../../common/errors");
var _common = require("../../../common");
var _audit_logging = require("../audit_logging");
var _utils = require("./utils");
/*
 * 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 queryOptions = Object.freeze({
  ignore: [404]
});
const createAction = async (esClient, action) => {
  try {
    const document = {
      ...action,
      action_id: action.action_id || (0, _uuid.v4)(),
      '@timestamp': action['@timestamp'] || new Date().toISOString()
    };
    await esClient.create({
      index: _common.AGENT_ACTIONS_INDEX,
      // doc id is same as action_id
      id: document.action_id,
      document,
      refresh: 'wait_for'
    }, {
      meta: true
    });
    _audit_logging.auditLoggingService.writeCustomAuditLog({
      message: `User created Fleet action [id=${action.action_id}, user_id=${action.user_id}, input_type=${action.input_type}]`
    });
    return document;
  } catch (createActionError) {
    throw new _errors.FleetActionsError(`Error creating action: ${createActionError.message}`, createActionError);
  }
};
exports.createAction = createAction;
const getLoggingInfo = ({
  id,
  actions
}) => {
  const action = actions.find(item => item.action_id === id);
  return {
    input_type: (action === null || action === void 0 ? void 0 : action.input_type) || '',
    user_id: (action === null || action === void 0 ? void 0 : action.user_id) || ''
  };
};
const bulkCreateActions = async (esClient, _actions) => {
  const actions = [];
  const bulkCreateActionsOperations = _actions.reduce((acc, action) => {
    // doc id is same as action_id
    const actionId = action.action_id || (0, _uuid.v4)();
    acc.push({
      create: {
        _index: _common.AGENT_ACTIONS_INDEX,
        _id: actionId
      }
    });
    const actionDoc = {
      ...action,
      action_id: actionId,
      '@timestamp': action['@timestamp'] || new Date().toISOString()
    };
    acc.push(actionDoc);
    actions.push(actionDoc);
    return acc;
  }, []);
  try {
    const bulkCreateActionsResponse = await esClient.bulk({
      operations: bulkCreateActionsOperations,
      refresh: 'wait_for'
    });
    const responseItems = bulkCreateActionsResponse.items;
    responseItems.forEach(item => {
      var _item$create;
      if (!((_item$create = item.create) !== null && _item$create !== void 0 && _item$create.error)) {
        var _item$create$_id, _item$create2;
        const id = (_item$create$_id = (_item$create2 = item.create) === null || _item$create2 === void 0 ? void 0 : _item$create2._id) !== null && _item$create$_id !== void 0 ? _item$create$_id : '';
        const loggingInfo = getLoggingInfo({
          id,
          actions
        });
        _audit_logging.auditLoggingService.writeCustomAuditLog({
          message: `User created Fleet action [id=${id}, user_id=${loggingInfo.user_id}, input_type=${loggingInfo.input_type}]`
        });
      }
    });
    const status = responseItems.every(item => {
      var _item$create3;
      return (_item$create3 = item.create) === null || _item$create3 === void 0 ? void 0 : _item$create3.error;
    }) ? 'failed' : responseItems.some(item => {
      var _item$create4;
      return (_item$create4 = item.create) === null || _item$create4 === void 0 ? void 0 : _item$create4.error;
    }) ? 'mixed' : 'success';
    return {
      status,
      items: responseItems.map(item => {
        var _item$create5, _item$create$_id2, _item$create6;
        return {
          status: (_item$create5 = item.create) !== null && _item$create5 !== void 0 && _item$create5.error ? 'error' : 'success',
          id: (_item$create$_id2 = (_item$create6 = item.create) === null || _item$create6 === void 0 ? void 0 : _item$create6._id) !== null && _item$create$_id2 !== void 0 ? _item$create$_id2 : ''
        };
      })
    };
  } catch (createBulkActionsError) {
    throw new _errors.FleetActionsError(`Error creating bulk actions: ${createBulkActionsError.message}`, createBulkActionsError);
  }
};
exports.bulkCreateActions = bulkCreateActions;
const getActionsByIds = async (esClient, actionIds) => {
  try {
    const getActionsResponse = await esClient.search({
      index: _common.AGENT_ACTIONS_INDEX,
      from: 0,
      size: _constants.ES_SEARCH_LIMIT,
      query: {
        bool: {
          filter: [{
            terms: {
              action_id: actionIds
            }
          }]
        }
      }
    }, queryOptions);
    const actions = getActionsResponse.hits.hits.reduce((acc, hit) => {
      if (hit._source) {
        acc.push(hit._source);
      }
      return acc;
    }, []);
    return {
      items: actions,
      total: actions.length
    };
  } catch (getActionsByIdError) {
    throw new _errors.FleetActionsError(`Error getting action: ${getActionsByIdError.message}`, getActionsByIdError);
  }
};
exports.getActionsByIds = getActionsByIds;
const getActionsWithKuery = async (esClient, kuery) => {
  const kueryNode = (0, _esQuery.fromKueryExpression)(kuery);
  const validationFilterKuery = (0, _utils.validateFilterKueryNode)({
    astFilter: kueryNode,
    types: _utils.ALLOWED_FLEET_ACTIONS_FIELD_TYPES,
    indexMapping: _utils.allowedFleetActionsFields,
    indexType: 'actions'
  });
  if (validationFilterKuery.some(obj => obj.error != null)) {
    const errors = validationFilterKuery.reduce((acc, item) => {
      if (item.error) {
        acc.push(item.error);
      }
      return acc;
    }, []).join();
    throw new _errors.FleetActionsError(`Kuery validation failed: ${errors}`);
  }
  try {
    const query = (0, _esQuery.toElasticsearchQuery)(kueryNode);
    const getActionSearchResponse = await esClient.search({
      index: _common.AGENT_ACTIONS_INDEX,
      from: 0,
      size: _constants.ES_SEARCH_LIMIT,
      query
    }, queryOptions);
    const actions = getActionSearchResponse.hits.hits.reduce((acc, hit) => {
      if (hit._source) {
        acc.push(hit._source);
      }
      return acc;
    }, []);
    return {
      items: actions,
      total: actions.length
    };
  } catch (getActionSearchError) {
    throw new _errors.FleetActionsError(`Error getting actions with kuery: ${getActionSearchError.message}`, getActionSearchError);
  }
};
exports.getActionsWithKuery = getActionsWithKuery;
const getActionResultsByIds = async (esClient, actionIds) => {
  try {
    const getActionsResultsResponse = await esClient.search({
      index: _common.AGENT_ACTIONS_RESULTS_INDEX,
      from: 0,
      size: _constants.ES_SEARCH_LIMIT,
      query: {
        bool: {
          filter: [{
            terms: {
              action_id: actionIds
            }
          }]
        }
      }
    }, queryOptions);
    const actionsResults = getActionsResultsResponse.hits.hits.reduce((acc, hit) => {
      if (hit._source) {
        acc.push(hit._source);
      }
      return acc;
    }, []);
    return {
      items: actionsResults,
      total: actionsResults.length
    };
  } catch (getActionByIdError) {
    throw new _errors.FleetActionsError(`Error getting action results: ${getActionByIdError.message}`, getActionByIdError);
  }
};
exports.getActionResultsByIds = getActionResultsByIds;
const getActionResultsWithKuery = async (esClient, kuery) => {
  const kueryNode = (0, _esQuery.fromKueryExpression)(kuery);
  const validationFilterKuery = (0, _utils.validateFilterKueryNode)({
    astFilter: kueryNode,
    types: _utils.ALLOWED_FLEET_ACTIONS_FIELD_TYPES,
    indexMapping: _utils.allowedFleetActionsFields,
    indexType: 'results'
  });
  if (validationFilterKuery.some(obj => obj.error != null)) {
    const errors = validationFilterKuery.reduce((acc, item) => {
      if (item.error) {
        acc.push(item.error);
      }
      return acc;
    }, []).join();
    throw new _errors.FleetActionsError(`Kuery validation failed: ${errors}`);
  }
  try {
    const query = (0, _esQuery.toElasticsearchQuery)(kueryNode);
    const getActionSearchResponse = await esClient.search({
      index: _common.AGENT_ACTIONS_INDEX,
      from: 0,
      size: _constants.ES_SEARCH_LIMIT,
      query
    }, queryOptions);
    const actionsResults = getActionSearchResponse.hits.hits.reduce((acc, hit) => {
      if (hit._source) {
        acc.push(hit._source);
      }
      return acc;
    }, []);
    return {
      items: actionsResults,
      total: actionsResults.length
    };
  } catch (getActionResultsSearchError) {
    throw new _errors.FleetActionsError(`Error getting action results with kuery: ${getActionResultsSearchError.message}`, getActionResultsSearchError);
  }
};
exports.getActionResultsWithKuery = getActionResultsWithKuery;