"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.cleanPreconfiguredOutputs = cleanPreconfiguredOutputs;
exports.createOrUpdatePreconfiguredOutputs = createOrUpdatePreconfiguredOutputs;
exports.ensurePreconfiguredOutputs = ensurePreconfiguredOutputs;
exports.getPreconfiguredOutputFromConfig = getPreconfiguredOutputFromConfig;
var _lodash = require("lodash");
var _jsYaml = require("js-yaml");
var _services = require("../../../common/services");
var _constants = require("../../constants");
var _output = require("../output");
var _agent_policy = require("../agent_policy");
var _app_context = require("../app_context");
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.
 */

function getPreconfiguredOutputFromConfig(config) {
  const {
    outputs: outputsOrUndefined
  } = config;
  const outputs = (outputsOrUndefined || []).concat([...(config !== null && config !== void 0 && config.agents.elasticsearch.hosts ? [{
    ..._constants.DEFAULT_OUTPUT,
    id: _constants.DEFAULT_OUTPUT_ID,
    hosts: config === null || config === void 0 ? void 0 : config.agents.elasticsearch.hosts,
    ca_sha256: config === null || config === void 0 ? void 0 : config.agents.elasticsearch.ca_sha256,
    ca_trusted_fingerprint: config === null || config === void 0 ? void 0 : config.agents.elasticsearch.ca_trusted_fingerprint,
    is_preconfigured: true
  }] : [])]);
  return outputs;
}
async function ensurePreconfiguredOutputs(soClient, esClient, outputs) {
  await createOrUpdatePreconfiguredOutputs(soClient, esClient, outputs);
  await cleanPreconfiguredOutputs(soClient, esClient, outputs);
}
async function createOrUpdatePreconfiguredOutputs(soClient, esClient, outputs) {
  const logger = _app_context.appContextService.getLogger();
  if (outputs.length === 0) {
    return;
  }
  const existingOutputs = await _output.outputService.bulkGet(soClient, outputs.map(({
    id
  }) => id), {
    ignoreNotFound: true
  });
  await Promise.all(outputs.map(async output => {
    var _outputData$ca_sha, _outputData$ca_truste, _outputData$ssl;
    const existingOutput = existingOutputs.find(o => o.id === output.id);
    const {
      id,
      config,
      ...outputData
    } = output;
    const configYaml = config ? (0, _jsYaml.safeDump)(config) : undefined;
    const data = {
      ...outputData,
      is_preconfigured: true,
      config_yaml: configYaml !== null && configYaml !== void 0 ? configYaml : null,
      // Set value to null to update these fields on update
      ca_sha256: (_outputData$ca_sha = outputData.ca_sha256) !== null && _outputData$ca_sha !== void 0 ? _outputData$ca_sha : null,
      ca_trusted_fingerprint: (_outputData$ca_truste = outputData.ca_trusted_fingerprint) !== null && _outputData$ca_truste !== void 0 ? _outputData$ca_truste : null,
      ssl: (_outputData$ssl = outputData.ssl) !== null && _outputData$ssl !== void 0 ? _outputData$ssl : null
    };
    if (!data.hosts || data.hosts.length === 0) {
      data.hosts = _output.outputService.getDefaultESHosts();
    }
    const isCreate = !existingOutput;

    // field in allow edit are not updated through preconfiguration
    if (!isCreate && output.allow_edit) {
      for (const key of output.allow_edit) {
        // @ts-expect-error
        data[key] = existingOutput[key];
      }
    }
    const isUpdateWithNewData = existingOutput && isPreconfiguredOutputDifferentFromCurrent(existingOutput, data);
    if (isCreate) {
      logger.debug(`Creating output ${output.id}`);
      await _output.outputService.create(soClient, esClient, data, {
        id,
        fromPreconfiguration: true
      });
    } else if (isUpdateWithNewData) {
      logger.debug(`Updating output ${output.id}`);
      await _output.outputService.update(soClient, esClient, id, data, {
        fromPreconfiguration: true
      });
      // Bump revision of all policies using that output
      if (outputData.is_default || outputData.is_default_monitoring) {
        await _agent_policy.agentPolicyService.bumpAllAgentPolicies(soClient, esClient);
      } else {
        await _agent_policy.agentPolicyService.bumpAllAgentPoliciesForOutput(soClient, esClient, id);
      }
    }
  }));
}
async function cleanPreconfiguredOutputs(soClient, esClient, outputs) {
  const existingOutputs = await _output.outputService.list(soClient);
  const existingPreconfiguredOutput = existingOutputs.items.filter(o => o.is_preconfigured === true);
  const logger = _app_context.appContextService.getLogger();
  for (const output of existingPreconfiguredOutput) {
    const hasBeenDelete = !outputs.find(({
      id
    }) => output.id === id);
    if (!hasBeenDelete) {
      continue;
    }
    if (output.is_default) {
      logger.info(`Updating default preconfigured output ${output.id} is no longer preconfigured`);
      await _output.outputService.update(soClient, esClient, output.id, {
        is_preconfigured: false
      }, {
        fromPreconfiguration: true
      });
    } else if (output.is_default_monitoring) {
      logger.info(`Updating default preconfigured output ${output.id} is no longer preconfigured`);
      await _output.outputService.update(soClient, esClient, output.id, {
        is_preconfigured: false
      }, {
        fromPreconfiguration: true
      });
    } else {
      logger.info(`Deleting preconfigured output ${output.id}`);
      await _output.outputService.delete(soClient, output.id, {
        fromPreconfiguration: true
      });
    }
  }
}
function isPreconfiguredOutputDifferentFromCurrent(existingOutput, preconfiguredOutput) {
  var _existingOutput$hosts, _existingOutput$allow, _preconfiguredOutput$;
  const kafkaFieldsAreDifferent = () => {
    if (existingOutput.type !== 'kafka' || preconfiguredOutput.type !== 'kafka') {
      return false;
    }
    return (0, _utils.isDifferent)(existingOutput.client_id, preconfiguredOutput.client_id) || (0, _utils.isDifferent)(existingOutput.version, preconfiguredOutput.version) || (0, _utils.isDifferent)(existingOutput.key, preconfiguredOutput.key) || (0, _utils.isDifferent)(existingOutput.compression, preconfiguredOutput.compression) || (0, _utils.isDifferent)(existingOutput.compression_level, preconfiguredOutput.compression_level) || (0, _utils.isDifferent)(existingOutput.auth_type, preconfiguredOutput.auth_type) || (0, _utils.isDifferent)(existingOutput.connection_type, preconfiguredOutput.connection_type) || (0, _utils.isDifferent)(existingOutput.username, preconfiguredOutput.username) || (0, _utils.isDifferent)(existingOutput.password, preconfiguredOutput.password) || (0, _utils.isDifferent)(existingOutput.sasl, preconfiguredOutput.sasl) || (0, _utils.isDifferent)(existingOutput.partition, preconfiguredOutput.partition) || (0, _utils.isDifferent)(existingOutput.random, preconfiguredOutput.random) || (0, _utils.isDifferent)(existingOutput.round_robin, preconfiguredOutput.round_robin) || (0, _utils.isDifferent)(existingOutput.hash, preconfiguredOutput.hash) || (0, _utils.isDifferent)(existingOutput.topics, preconfiguredOutput.topics) || (0, _utils.isDifferent)(existingOutput.headers, preconfiguredOutput.headers) || (0, _utils.isDifferent)(existingOutput.timeout, preconfiguredOutput.timeout) || (0, _utils.isDifferent)(existingOutput.broker_timeout, preconfiguredOutput.broker_timeout) || (0, _utils.isDifferent)(existingOutput.required_acks, preconfiguredOutput.required_acks);
  };
  return !existingOutput.is_preconfigured || (0, _utils.isDifferent)(existingOutput.is_default, preconfiguredOutput.is_default) || (0, _utils.isDifferent)(existingOutput.is_default_monitoring, preconfiguredOutput.is_default_monitoring) || (0, _utils.isDifferent)(existingOutput.name, preconfiguredOutput.name) || (0, _utils.isDifferent)(existingOutput.type, preconfiguredOutput.type) || preconfiguredOutput.hosts && !(0, _lodash.isEqual)((existingOutput === null || existingOutput === void 0 ? void 0 : existingOutput.type) === 'elasticsearch' ? (_existingOutput$hosts = existingOutput.hosts) === null || _existingOutput$hosts === void 0 ? void 0 : _existingOutput$hosts.map(_services.normalizeHostsForAgents) : existingOutput.hosts, preconfiguredOutput.type === 'elasticsearch' ? preconfiguredOutput.hosts.map(_services.normalizeHostsForAgents) : preconfiguredOutput.hosts) || (0, _utils.isDifferent)(preconfiguredOutput.ssl, existingOutput.ssl) || (0, _utils.isDifferent)(existingOutput.ca_sha256, preconfiguredOutput.ca_sha256) || (0, _utils.isDifferent)(existingOutput.ca_trusted_fingerprint, preconfiguredOutput.ca_trusted_fingerprint) || (0, _utils.isDifferent)(existingOutput.config_yaml, preconfiguredOutput.config_yaml) || (0, _utils.isDifferent)(existingOutput.proxy_id, preconfiguredOutput.proxy_id) || (0, _utils.isDifferent)((_existingOutput$allow = existingOutput.allow_edit) !== null && _existingOutput$allow !== void 0 ? _existingOutput$allow : [], (_preconfiguredOutput$ = preconfiguredOutput.allow_edit) !== null && _preconfiguredOutput$ !== void 0 ? _preconfiguredOutput$ : []) || kafkaFieldsAreDifferent();
}