"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.UpdateButton = void 0;
var _react = _interopRequireWildcard(require("react"));
var _reactRouterDom = require("react-router-dom");
var _i18n = require("@kbn/i18n");
var _i18nReact = require("@kbn/i18n-react");
var _eui = require("@elastic/eui");
var _public = require("@kbn/kibana-react-plugin/public");
var _types = require("../../../../../types");
var _constants = require("../../../../../constants");
var _hooks = require("../../../../../hooks");
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
/*
 * 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.
 */

/*

  Updating an integration to a new version entails a bit of logic. We allow the user to choose whether they'd like to
  simultaneously upgrade any package policies that include the current version of the integration. For example, if
  a user is running four agent policies that include the `nginx-0.2.4` package and they update to `nginx-0.7.0`, they
  can elect to also deploy the new integration version to any agent running one of those four agent policies.

  If the user does not elect to upgrade their running policies, we simply install the latest version of the package and
  navigate to the new version's settings page, e.g. `/detail/nginx-0.7.0/settings`.

  If the user _does_ elect to upgrade their running policies, we display a confirmation modal. In this modal, we'll report the
  number of agents and policies that will be affected by the upgrade, and if there are any conflicts. In the case of a conflict
  between versions, an upgrade for a given package policy will be skipped and the user will need to manually recreate their policy
  to resolve any breaking changes between versions. Once the user confirms, we first install the latest version of the integration,
  then we make a call to the "upgrade policies" API endpoint with a list of all package policy ID's that include the current version
  of the integration. This API endpoint will complete the upgrade process in bulk for each package policy provided. Upon completion,
  we navigate to the new version's settings page, as above.

*/

const UpdateButton = ({
  dryRunData,
  isUpgradingPackagePolicies = false,
  name,
  packagePolicyIds = [],
  setIsUpgradingPackagePolicies = () => {},
  title,
  version,
  theme$
}) => {
  const history = (0, _reactRouterDom.useHistory)();
  const {
    getPath
  } = (0, _hooks.useLink)();
  const {
    notifications
  } = (0, _hooks.useStartServices)();
  const canUpgradePackages = (0, _hooks.useAuthz)().integrations.upgradePackages;
  const installPackage = (0, _hooks.useInstallPackage)();
  const getPackageInstallStatus = (0, _hooks.useGetPackageInstallStatus)();
  const {
    status: installationStatus
  } = getPackageInstallStatus(name);
  const isInstalling = installationStatus === _types.InstallStatus.installing;
  const [isUpdateModalVisible, setIsUpdateModalVisible] = (0, _react.useState)(false);
  const [upgradePackagePolicies, setUpgradePackagePolicies] = (0, _react.useState)(true);
  const {
    data: agentPolicyData
  } = (0, _hooks.useGetAgentPoliciesQuery)({
    perPage: _constants.SO_SEARCH_LIMIT,
    page: 1,
    // Fetch all agent policies that include one of the eligible package policies
    kuery: packagePolicyIds.length ? `${_constants.AGENT_POLICY_SAVED_OBJECT_TYPE}.package_policies:${packagePolicyIds.map(id => `"${id}"`).join(' or ')}` : ''
  });
  const packagePolicyCount = (0, _react.useMemo)(() => packagePolicyIds.length, [packagePolicyIds]);
  function isStringArray(arr) {
    return Array.isArray(arr) && arr.every(p => typeof p === 'string');
  }
  const agentCount = (0, _react.useMemo)(() => {
    if (!(agentPolicyData !== null && agentPolicyData !== void 0 && agentPolicyData.items)) return 0;
    return agentPolicyData.items.reduce((acc, item) => {
      const existingPolicies = item !== null && item !== void 0 && item.package_policies ? isStringArray(item.package_policies) ? item.package_policies.filter(p => packagePolicyIds.includes(p)) : item.package_policies.filter(p => packagePolicyIds.includes(p.id)) : [];
      return acc += existingPolicies.length > 0 && item !== null && item !== void 0 && item.agents ? item === null || item === void 0 ? void 0 : item.agents : 0;
    }, 0);
  }, [agentPolicyData, packagePolicyIds]);
  const conflictCount = (0, _react.useMemo)(() => dryRunData === null || dryRunData === void 0 ? void 0 : dryRunData.filter(item => item.hasErrors).length, [dryRunData]);
  const handleUpgradePackagePoliciesChange = (0, _react.useCallback)(() => {
    setUpgradePackagePolicies(prev => !prev);
  }, []);
  const navigateToNewSettingsPage = (0, _react.useCallback)(() => {
    // only navigate if still on old settings page (user has not navigated away)
    if (!history.location.pathname.match(getPath('integration_details_settings', {
      pkgkey: `${name}-.*`
    }))) {
      return;
    }
    const settingsPath = getPath('integration_details_settings', {
      pkgkey: `${name}-${version}`
    });
    history.push(settingsPath);
  }, [history, getPath, name, version]);
  const handleClickUpdate = (0, _react.useCallback)(async () => {
    await installPackage({
      name,
      version,
      title,
      fromUpdate: true
    });
  }, [installPackage, name, title, version]);
  const upgradePackagePoliciesMutation = (0, _hooks.useUpgradePackagePoliciesMutation)();
  const handleClickUpgradePolicies = (0, _react.useCallback)(async () => {
    if (isUpgradingPackagePolicies) {
      return;
    }
    setIsUpdateModalVisible(false);
    setIsUpgradingPackagePolicies(true);
    await installPackage({
      name,
      version,
      title
    });
    upgradePackagePoliciesMutation.mutate({
      // Only upgrade policies that don't have conflicts
      packagePolicyIds: packagePolicyIds.filter(id => {
        var _dryRunData$find;
        return !(dryRunData !== null && dryRunData !== void 0 && (_dryRunData$find = dryRunData.find(dryRunRecord => {
          var _dryRunRecord$diff;
          return ((_dryRunRecord$diff = dryRunRecord.diff) === null || _dryRunRecord$diff === void 0 ? void 0 : _dryRunRecord$diff[0].id) === id;
        })) !== null && _dryRunData$find !== void 0 && _dryRunData$find.hasErrors);
      })
    }, {
      onSuccess: () => {
        notifications.toasts.addSuccess({
          title: (0, _public.toMountPoint)( /*#__PURE__*/_react.default.createElement(_i18nReact.FormattedMessage, {
            id: "xpack.fleet.integrations.packageUpdateSuccessTitle",
            defaultMessage: "Updated {title} and upgraded policies",
            values: {
              title
            }
          }), {
            theme$
          }),
          text: (0, _public.toMountPoint)( /*#__PURE__*/_react.default.createElement(_i18nReact.FormattedMessage, {
            id: "xpack.fleet.integrations.packageUpdateSuccessDescription",
            defaultMessage: "Successfully updated {title} and upgraded policies",
            values: {
              title
            }
          }), {
            theme$
          })
        });
        navigateToNewSettingsPage();
      }
    });
  }, [isUpgradingPackagePolicies, setIsUpgradingPackagePolicies, installPackage, name, version, title, upgradePackagePoliciesMutation, packagePolicyIds, dryRunData, notifications.toasts, theme$, navigateToNewSettingsPage]);
  const updateModal = /*#__PURE__*/_react.default.createElement(_eui.EuiConfirmModal, {
    isLoading: isUpgradingPackagePolicies,
    maxWidth: 568,
    onCancel: () => {
      setIsUpdateModalVisible(false);
    },
    cancelButtonText: _i18n.i18n.translate('xpack.fleet.integrations.settings.confirmUpdateModal.cancel', {
      defaultMessage: 'Cancel'
    }),
    onConfirm: handleClickUpgradePolicies,
    confirmButtonText: _i18n.i18n.translate('xpack.fleet.integrations.settings.confirmUpdateModal.confirm', {
      defaultMessage: 'Upgrade {packageName} and policies',
      values: {
        packageName: title
      }
    }),
    title: _i18n.i18n.translate('xpack.fleet.integrations.settings.confirmUpdateModal.updateTitle', {
      defaultMessage: 'Upgrade {packageName} and policies',
      values: {
        packageName: title
      }
    })
  }, /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, conflictCount && conflictCount > 0 ? /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_eui.EuiCallOut, {
    color: "warning",
    iconType: "warning",
    title: _i18n.i18n.translate('xpack.fleet.integrations.settings.confirmUpdateModal.conflictCallOut.title', {
      defaultMessage: 'Some integration policies have conflicts'
    })
  }, /*#__PURE__*/_react.default.createElement("strong", null, /*#__PURE__*/_react.default.createElement(_i18nReact.FormattedMessage, {
    id: "xpack.fleet.integrations.settings.confirmUpdateModal.conflictCallOut.integrationPolicyCount",
    defaultMessage: "{conflictCount, plural, one { # integration policy} other { # integration policies}}",
    values: {
      conflictCount
    }
  })), ' ', /*#__PURE__*/_react.default.createElement(_i18nReact.FormattedMessage, {
    id: "xpack.fleet.integrations.settings.confirmUpdateModal.conflictCallOut.body",
    defaultMessage: "{conflictCount, plural, one { has} other { have}} conflicts and will not be upgraded automatically. You can manually resolve these conflicts via agent policy settings in Fleet after performing this upgrade.",
    values: {
      conflictCount
    }
  })), /*#__PURE__*/_react.default.createElement(_eui.EuiSpacer, {
    size: "l"
  })) : null, /*#__PURE__*/_react.default.createElement(_i18nReact.FormattedMessage, {
    id: "xpack.fleet.integrations.settings.confirmUpdateModal.body",
    defaultMessage: "This action will deploy updates to all agents which use these policies. Fleet has detected that {packagePolicyCountText} {packagePolicyCount, plural, one { is} other { are}} ready to be upgraded and {packagePolicyCount, plural, one { is} other { are}} already in use by {agentCountText}.",
    values: {
      packagePolicyCount,
      packagePolicyCountText: /*#__PURE__*/_react.default.createElement("strong", null, /*#__PURE__*/_react.default.createElement(_i18nReact.FormattedMessage, {
        id: "xpack.fleet.integrations.confirmUpdateModal.body.policyCount",
        defaultMessage: "{packagePolicyCount, plural, one {# integration policy} other {# integration policies}}",
        values: {
          packagePolicyCount
        }
      })),
      agentCountText: /*#__PURE__*/_react.default.createElement("strong", null, /*#__PURE__*/_react.default.createElement(_i18nReact.FormattedMessage, {
        id: "xpack.fleet.integrations.confirmUpdateModal.body.agentCount",
        defaultMessage: "{agentCount, plural, one {# agent} other {# agents}}",
        values: {
          agentCount
        }
      }))
    }
  })));
  return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_eui.EuiFlexGroup, {
    alignItems: "center"
  }, /*#__PURE__*/_react.default.createElement(_eui.EuiFlexItem, {
    grow: false
  }, /*#__PURE__*/_react.default.createElement(_eui.EuiButton, {
    isLoading: isInstalling || isUpgradingPackagePolicies,
    onClick: upgradePackagePolicies ? () => setIsUpdateModalVisible(true) : handleClickUpdate,
    "data-test-subj": "updatePackageBtn",
    isDisabled: !canUpgradePackages
  }, /*#__PURE__*/_react.default.createElement(_i18nReact.FormattedMessage, {
    id: "xpack.fleet.integrations.updatePackage.updatePackageButtonLabel",
    defaultMessage: "Upgrade to latest version"
  }))), packagePolicyCount > 0 && /*#__PURE__*/_react.default.createElement(_eui.EuiFlexItem, {
    grow: false
  }, /*#__PURE__*/_react.default.createElement(_eui.EuiCheckbox, {
    compressed: true,
    labelProps: {
      style: {
        display: 'flex'
      }
    },
    id: "upgradePoliciesCheckbox",
    "data-test-subj": "epmDetails.upgradePoliciesCheckbox",
    disabled: !canUpgradePackages,
    checked: upgradePackagePolicies,
    onChange: handleUpgradePackagePoliciesChange,
    label: _i18n.i18n.translate('xpack.fleet.integrations.updatePackage.upgradePoliciesCheckboxLabel', {
      defaultMessage: 'Upgrade integration policies'
    })
  }))), isUpdateModalVisible && updateModal);
};
exports.UpdateButton = UpdateButton;