"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.AddDomainLogic = void 0;
var _kea = require("kea");
var _i18n = require("@kbn/i18n");
var _constants = require("../../../../../../shared/constants");
var _encode_path_params = require("../../../../../../shared/encode_path_params");
var _flash_messages = require("../../../../../../shared/flash_messages");
var _handle_api_errors = require("../../../../../../shared/flash_messages/handle_api_errors");
var _http = require("../../../../../../shared/http");
var _kibana = require("../../../../../../shared/kibana");
var _utils = require("../../../../../api/crawler/utils");
var _routes = require("../../../../../routes");
var _index_name_logic = require("../../../index_name_logic");
var _crawler_logic = require("../../crawler_logic");
var _domain_management_logic = require("../domain_management_logic");
var _utils2 = 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 DEFAULT_SELECTOR_VALUES = {
  addDomainFormInputValue: 'https://',
  allowSubmit: false,
  domainValidationResult: {
    steps: {
      contentVerification: {
        state: ''
      },
      indexingRestrictions: {
        state: ''
      },
      initialValidation: {
        state: ''
      },
      networkConnectivity: {
        state: ''
      }
    }
  },
  entryPointValue: '/',
  ignoreValidationFailure: false,
  isValidationLoading: false
};
const AddDomainLogic = (0, _kea.kea)({
  path: ['enterprise_search', 'crawler', 'add_domain_logic'],
  actions: () => ({
    clearDomainFormInputValue: true,
    closeFlyout: true,
    initialValidation: true,
    onSubmitNewDomainError: errors => ({
      errors
    }),
    onSubmitNewDomainSuccess: domain => ({
      domain
    }),
    openFlyout: true,
    performDomainValidationStep: (stepName, checks) => ({
      checks,
      stepName
    }),
    setAddDomainFormInputValue: newValue => newValue,
    setDomainValidationResult: change => ({
      change
    }),
    setIgnoreValidationFailure: newValue => newValue,
    startDomainValidation: true,
    submitNewDomain: true,
    validateDomainContentVerification: true,
    validateDomainIndexingRestrictions: true,
    validateDomainInitialVerification: (newValue, newEntryPointValue) => ({
      newEntryPointValue,
      newValue
    }),
    validateDomainNetworkConnectivity: true
  }),
  reducers: () => ({
    addDomainFormInputValue: [DEFAULT_SELECTOR_VALUES.addDomainFormInputValue, {
      clearDomainFormInputValue: () => DEFAULT_SELECTOR_VALUES.addDomainFormInputValue,
      setAddDomainFormInputValue: (_, newValue) => newValue,
      validateDomainInitialVerification: (_, {
        newValue
      }) => newValue
    }],
    domainValidationResult: [DEFAULT_SELECTOR_VALUES.domainValidationResult, {
      clearDomainFormInputValue: () => DEFAULT_SELECTOR_VALUES.domainValidationResult,
      setAddDomainFormInputValue: () => DEFAULT_SELECTOR_VALUES.domainValidationResult,
      setDomainValidationResult: ({
        steps
      }, {
        change
      }) => ({
        steps: {
          ...steps,
          ...change
        }
      }),
      startDomainValidation: () => ({
        steps: {
          contentVerification: {
            state: 'loading'
          },
          indexingRestrictions: {
            state: 'loading'
          },
          initialValidation: {
            state: 'loading'
          },
          networkConnectivity: {
            state: 'loading'
          }
        }
      })
    }],
    entryPointValue: [DEFAULT_SELECTOR_VALUES.entryPointValue, {
      clearDomainFormInputValue: () => DEFAULT_SELECTOR_VALUES.entryPointValue,
      setAddDomainFormInputValue: () => DEFAULT_SELECTOR_VALUES.entryPointValue,
      validateDomainInitialVerification: (_, {
        newEntryPointValue
      }) => newEntryPointValue
    }],
    errors: [[], {
      clearDomainFormInputValue: () => [],
      onSubmitNewDomainError: (_, {
        errors
      }) => errors,
      setAddDomainFormInputValue: () => [],
      submitNewDomain: () => [],
      validateDomainInitialVerification: () => []
    }],
    ignoreValidationFailure: [DEFAULT_SELECTOR_VALUES.ignoreValidationFailure, {
      clearDomainFormInputValue: () => DEFAULT_SELECTOR_VALUES.ignoreValidationFailure,
      setAddDomainFormInputValue: () => DEFAULT_SELECTOR_VALUES.ignoreValidationFailure,
      setIgnoreValidationFailure: (_, newValue) => newValue
    }],
    isFlyoutVisible: [false, {
      closeFlyout: () => false,
      onSubmitNewDomainSuccess: () => false,
      openFlyout: () => true
    }]
  }),
  selectors: ({
    selectors
  }) => ({
    allowSubmit: [() => [selectors.ignoreValidationFailure, selectors.hasValidationCompleted, selectors.hasBlockingFailure], (ignoreValidationFailure, hasValidationCompleted, hasBlockingFailure) => {
      if (ignoreValidationFailure) {
        return true;
      }
      return hasValidationCompleted && !hasBlockingFailure;
    }],
    canIgnoreValidationFailure: [() => [selectors.hasValidationCompleted, selectors.domainValidationResult], (hasValidationCompleted, domainValidationResult) => {
      if (!hasValidationCompleted) {
        return false;
      }
      return domainValidationResult.steps.indexingRestrictions.blockingFailure || domainValidationResult.steps.contentVerification.blockingFailure;
    }],
    displayValidation: [() => [selectors.isValidationLoading, selectors.hasValidationCompleted], (isValidationLoading, hasValidationCompleted) => isValidationLoading || hasValidationCompleted],
    hasBlockingFailure: [() => [selectors.domainValidationResult], domainValidationResult => !!Object.values(domainValidationResult.steps).find(step => step.blockingFailure)],
    hasValidationCompleted: [() => [selectors.domainValidationResult], domainValidationResult => !Object.values(domainValidationResult.steps).find(step => step.state === 'loading' || step.state === '')],
    isValidationLoading: [() => [selectors.domainValidationResult], domainValidationResult => !!Object.values(domainValidationResult.steps).find(step => step.state === 'loading')]
  }),
  listeners: ({
    actions,
    values
  }) => ({
    onSubmitNewDomainSuccess: ({
      domain
    }) => {
      const {
        indexName
      } = _index_name_logic.IndexNameLogic.values;
      (0, _flash_messages.flashSuccessToast)(_i18n.i18n.translate('xpack.enterpriseSearch.crawler.domainsTable.action.add.successMessage', {
        defaultMessage: "Successfully added domain '{domainUrl}'",
        values: {
          domainUrl: domain.url
        }
      }));
      _kibana.KibanaLogic.values.navigateToUrl((0, _encode_path_params.generateEncodedPath)(_routes.SEARCH_INDEX_CRAWLER_DOMAIN_DETAIL_PATH, {
        domainId: domain.id,
        indexName
      }));
      _crawler_logic.CrawlerLogic.actions.fetchCrawlerData();
      _domain_management_logic.DomainManagementLogic.actions.getDomains(_constants.DEFAULT_META);
      actions.clearDomainFormInputValue();
    },
    performDomainValidationStep: async ({
      stepName,
      checks
    }) => {
      const {
        http
      } = _http.HttpLogic.values;
      const failureResultChange = (0, _utils2.domainValidationFailureResultChange)(stepName);
      const route = '/internal/enterprise_search/crawler/validate_url';
      try {
        const data = await http.post(route, {
          body: JSON.stringify({
            checks,
            url: values.addDomainFormInputValue.trim()
          })
        });
        const result = (0, _utils.crawlDomainValidationToResult)(data);
        if (result.blockingFailure) {
          actions.setDomainValidationResult({
            [stepName]: result,
            ...failureResultChange
          });
        } else {
          actions.setDomainValidationResult({
            [stepName]: result
          });

          // Trigger next step
          switch (stepName) {
            case 'initialValidation':
              actions.validateDomainNetworkConnectivity();
              break;
            case 'networkConnectivity':
              actions.validateDomainIndexingRestrictions();
              break;
            case 'indexingRestrictions':
              actions.validateDomainContentVerification();
              break;
          }
        }
      } catch (e) {
        actions.setDomainValidationResult({
          [stepName]: {
            blockingFailure: true,
            message: _i18n.i18n.translate('xpack.enterpriseSearch.crawler.addDomainForm.unexpectedValidationErrorMessage', {
              defaultMessage: 'Unexpected error'
            }),
            state: 'invalid'
          },
          ...failureResultChange
        });
      }
    },
    startDomainValidation: async () => {
      const {
        domain,
        entryPoint
      } = (0, _utils2.extractDomainAndEntryPointFromUrl)(values.addDomainFormInputValue.trim());
      const domainWithProtocol = await (0, _utils2.getDomainWithProtocol)(domain);
      actions.validateDomainInitialVerification(domainWithProtocol, entryPoint);
    },
    submitNewDomain: async () => {
      const {
        http
      } = _http.HttpLogic.values;
      const {
        indexName
      } = _index_name_logic.IndexNameLogic.values;
      const requestBody = JSON.stringify({
        entry_points: [{
          value: values.entryPointValue
        }],
        name: values.addDomainFormInputValue.trim()
      });
      try {
        const response = await http.post(`/internal/enterprise_search/indices/${indexName}/crawler/domains`, {
          body: requestBody
        });
        const domain = (0, _utils.crawlerDomainServerToClient)(response);
        actions.onSubmitNewDomainSuccess(domain);
      } catch (e) {
        // we surface errors inside the form instead of in flash messages
        const errorMessages = (0, _handle_api_errors.getErrorsFromHttpResponse)(e);
        actions.onSubmitNewDomainError(errorMessages);
      }
    },
    validateDomainContentVerification: () => {
      actions.performDomainValidationStep('contentVerification', ['url_request', 'url_content']);
    },
    validateDomainIndexingRestrictions: () => {
      actions.performDomainValidationStep('indexingRestrictions', ['robots_txt']);
    },
    validateDomainInitialVerification: () => {
      actions.performDomainValidationStep('initialValidation', ['url']);
    },
    validateDomainNetworkConnectivity: () => {
      actions.performDomainValidationStep('networkConnectivity', ['dns', 'tcp']);
    }
  })
});
exports.AddDomainLogic = AddDomainLogic;