"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.AddSourceSteps = exports.AddSourceLogic = void 0;
var _kea = require("kea");
var _lodash = require("lodash");
var _i18n = require("@kbn/i18n");
var _flash_messages = require("../../../../../shared/flash_messages");
var _http = require("../../../../../shared/http");
var _kibana = require("../../../../../shared/kibana");
var _app_logic = require("../../../../app_logic");
var _routes = require("../../../../routes");
var _constants = require("../../constants");
var _source_data = require("../../source_data");
var _sources_logic = require("../../sources_logic");
var _external_connector_logic = require("./add_external_connector/external_connector_logic");
/*
 * 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.
 */
let AddSourceSteps;
exports.AddSourceSteps = AddSourceSteps;
(function (AddSourceSteps) {
  AddSourceSteps["SaveConfigStep"] = "Save Config";
  AddSourceSteps["ConfigCompletedStep"] = "Config Completed";
  AddSourceSteps["ConnectInstanceStep"] = "Connect Instance";
  AddSourceSteps["ConfigureOauthStep"] = "Configure Oauth";
  AddSourceSteps["ReauthenticateStep"] = "Reauthenticate";
})(AddSourceSteps || (exports.AddSourceSteps = AddSourceSteps = {}));
const AddSourceLogic = (0, _kea.kea)({
  path: ['enterprise_search', 'workplace_search', 'add_source_logic'],
  actions: {
    setAddSourceStep: addSourceCurrentStep => addSourceCurrentStep,
    setSourceConfigData: sourceConfigData => sourceConfigData,
    setSourceConnectData: sourceConnectData => sourceConnectData,
    setConfiguredField: (key, value) => ({
      key,
      value
    }),
    setSourceLoginValue: loginValue => loginValue,
    setSourcePasswordValue: passwordValue => passwordValue,
    setSourceSubdomainValue: subdomainValue => subdomainValue,
    setSourceIndexPermissionsValue: indexPermissionsValue => indexPermissionsValue,
    setPreContentSourceConfigData: data => data,
    setPreContentSourceId: preContentSourceId => preContentSourceId,
    setSelectedGithubOrganizations: option => option,
    getSourceConfigData: () => true,
    getSourceConnectData: successCallback => ({
      successCallback
    }),
    getSourceReConnectData: sourceId => ({
      sourceId
    }),
    getPreContentSourceConfigData: () => true,
    saveSourceConfig: (isUpdating, successCallback) => ({
      isUpdating,
      successCallback
    }),
    saveSourceParams: (search, params, isOrganization) => ({
      search,
      params,
      isOrganization
    }),
    createContentSource: (successCallback, errorCallback) => ({
      successCallback,
      errorCallback
    }),
    resetSourceState: () => true,
    setButtonNotLoading: () => true,
    setFirstStep: () => true
  },
  reducers: ({
    props
  }) => ({
    addSourceCurrentStep: [null, {
      setAddSourceStep: (_, addSourceCurrentStep) => addSourceCurrentStep
    }],
    sourceConfigData: [{}, {
      setSourceConfigData: (_, sourceConfigData) => sourceConfigData
    }],
    sourceConnectData: [{}, {
      setSourceConnectData: (_, sourceConnectData) => sourceConnectData
    }],
    dataLoading: [true, {
      setSourceConfigData: () => false,
      resetSourceState: () => false,
      setPreContentSourceConfigData: () => false,
      getSourceConfigData: () => true
    }],
    buttonLoading: [false, {
      setButtonNotLoading: () => false,
      setSourceConnectData: () => false,
      setSourceConfigData: () => false,
      resetSourceState: () => false,
      saveSourceConfig: () => true,
      getSourceConnectData: () => true,
      createContentSource: () => true
    }],
    sectionLoading: [true, {
      getPreContentSourceConfigData: () => true,
      setPreContentSourceConfigData: () => false
    }],
    loginValue: ['', {
      setSourceLoginValue: (_, loginValue) => loginValue,
      resetSourceState: () => ''
    }],
    passwordValue: ['', {
      setSourcePasswordValue: (_, passwordValue) => passwordValue,
      resetSourceState: () => ''
    }],
    subdomainValue: ['', {
      setSourceSubdomainValue: (_, subdomainValue) => subdomainValue,
      resetSourceState: () => ''
    }],
    indexPermissionsValue: [false, {
      setSourceIndexPermissionsValue: (_, indexPermissionsValue) => indexPermissionsValue,
      resetSourceState: () => false
    }],
    githubOrganizations: [[], {
      setPreContentSourceConfigData: (_, {
        githubOrganizations
      }) => githubOrganizations,
      resetSourceState: () => []
    }],
    selectedGithubOrganizationsMap: [{}, {
      setSelectedGithubOrganizations: (state, option) => ({
        ...state,
        ...{
          [option]: !state[option]
        }
      }),
      resetSourceState: () => ({})
    }],
    preContentSourceId: ['', {
      setPreContentSourceId: (_, preContentSourceId) => preContentSourceId,
      setPreContentSourceConfigData: () => '',
      resetSourceState: () => ''
    }],
    oauthConfigCompleted: [false, {
      setPreContentSourceConfigData: () => true
    }],
    sourceData: [(0, _source_data.getSourceData)(props.serviceType) || null, {}],
    configuredFields: [{}, {
      setSourceConfigData: (_, {
        configuredFields
      }) => configuredFields,
      setConfiguredField: (configuredFields, {
        key,
        value
      }) => ({
        ...configuredFields,
        [key]: value
      }),
      resetSourceState: () => ({})
    }]
  }),
  selectors: ({
    selectors
  }) => ({
    selectedGithubOrganizations: [() => [selectors.selectedGithubOrganizationsMap], orgsMap => (0, _lodash.keys)((0, _lodash.pickBy)(orgsMap))]
  }),
  listeners: ({
    actions,
    values,
    props
  }) => ({
    getSourceConfigData: async () => {
      const {
        serviceType
      } = props;
      // TODO: Once multi-config support for connectors is added, this request url will need to include an ID
      const route = `/internal/workplace_search/org/settings/connectors/${serviceType}`;
      try {
        const response = await _http.HttpLogic.values.http.get(route);
        actions.setSourceConfigData(response);
        actions.setFirstStep();
      } catch (e) {
        (0, _flash_messages.flashAPIErrors)(e);
      }
    },
    getSourceConnectData: async ({
      successCallback
    }) => {
      const {
        serviceType
      } = props;
      (0, _flash_messages.clearFlashMessages)();
      const {
        isOrganization
      } = _app_logic.AppLogic.values;
      const {
        subdomainValue: subdomain,
        indexPermissionsValue: indexPermissions
      } = values;
      const route = isOrganization ? `/internal/workplace_search/org/sources/${serviceType}/prepare` : `/internal/workplace_search/account/sources/${serviceType}/prepare`;
      const indexPermissionsQuery = isOrganization ? {
        index_permissions: indexPermissions
      } : undefined;
      const query = subdomain ? {
        ...indexPermissionsQuery,
        subdomain
      } : {
        ...indexPermissionsQuery
      };
      try {
        const response = await _http.HttpLogic.values.http.get(route, {
          query
        });
        actions.setSourceConnectData(response);
        successCallback(response.oauthUrl);
      } catch (e) {
        (0, _flash_messages.flashAPIErrors)(e);
      } finally {
        actions.setButtonNotLoading();
      }
    },
    getSourceReConnectData: async ({
      sourceId
    }) => {
      const {
        isOrganization
      } = _app_logic.AppLogic.values;
      const route = isOrganization ? `/internal/workplace_search/org/sources/${sourceId}/reauth_prepare` : `/internal/workplace_search/account/sources/${sourceId}/reauth_prepare`;
      try {
        const response = await _http.HttpLogic.values.http.get(route);
        actions.setSourceConnectData(response);
      } catch (e) {
        (0, _flash_messages.flashAPIErrors)(e);
      }
    },
    getPreContentSourceConfigData: async () => {
      const {
        isOrganization
      } = _app_logic.AppLogic.values;
      const {
        preContentSourceId
      } = values;
      const route = isOrganization ? `/internal/workplace_search/org/pre_sources/${preContentSourceId}` : `/internal/workplace_search/account/pre_sources/${preContentSourceId}`;
      try {
        const response = await _http.HttpLogic.values.http.get(route);
        actions.setPreContentSourceConfigData(response);
      } catch (e) {
        (0, _flash_messages.flashAPIErrors)(e);
      }
    },
    saveSourceConfig: async ({
      isUpdating,
      successCallback
    }) => {
      (0, _flash_messages.clearFlashMessages)();
      const {
        serviceType
      } = props;
      const {
        externalConnectorUrl,
        externalConnectorApiKey
      } = _external_connector_logic.ExternalConnectorLogic.values;
      if (serviceType === 'external' && externalConnectorUrl && !(0, _external_connector_logic.isValidExternalUrl)(externalConnectorUrl)) {
        _external_connector_logic.ExternalConnectorLogic.actions.setUrlValidation(false);
        actions.setButtonNotLoading();
        return;
      }
      const route = isUpdating ? `/internal/workplace_search/org/settings/connectors/${serviceType}` : '/internal/workplace_search/org/settings/connectors';
      const http = isUpdating ? _http.HttpLogic.values.http.put : _http.HttpLogic.values.http.post;
      const params = {
        ...values.configuredFields,
        external_connector_url: serviceType === 'external' ? externalConnectorUrl : undefined,
        external_connector_api_key: serviceType === 'external' ? externalConnectorApiKey : undefined,
        service_type: serviceType
      };
      try {
        const response = await http(route, {
          body: JSON.stringify(params)
        });
        if (successCallback) successCallback();
        if (isUpdating) {
          (0, _flash_messages.flashSuccessToast)(_i18n.i18n.translate('xpack.enterpriseSearch.workplaceSearch.sources.flashMessages.contentSourceConfigUpdated', {
            defaultMessage: 'Successfully updated configuration.'
          }));
        }
        actions.setSourceConfigData(response);
      } catch (e) {
        (0, _flash_messages.flashAPIErrors)(e);
      } finally {
        actions.setButtonNotLoading();
      }
    },
    saveSourceParams: async ({
      search,
      params,
      isOrganization
    }) => {
      const {
        http
      } = _http.HttpLogic.values;
      const {
        navigateToUrl
      } = _kibana.KibanaLogic.values;
      const {
        setAddedSource
      } = _sources_logic.SourcesLogic.actions;
      const query = {
        ...params
      };
      const route = '/internal/workplace_search/sources/create';

      /**
      There is an extreme edge case where the user is trying to connect Github as source from ent-search,
      after configuring it in Kibana. When this happens, Github redirects the user from ent-search to Kibana
      with special error properties in the query params. In this case we need to redirect the user to the
      app home page and display the error message, and not persist the other query params to the server.
      */
      if (params.error_description) {
        navigateToUrl(isOrganization ? '/' : _routes.PRIVATE_SOURCES_PATH);
        (0, _flash_messages.setErrorMessage)(isOrganization ? params.error_description : (0, _constants.PERSONAL_DASHBOARD_SOURCE_ERROR)(params.error_description));
        return;
      }
      try {
        const response = await http.get(route, {
          query
        });
        const {
          serviceName,
          indexPermissions,
          serviceType,
          preContentSourceId,
          hasConfigureStep
        } = response;

        // GitHub requires an intermediate configuration step, where we collect the repos to index.
        if (hasConfigureStep && !values.oauthConfigCompleted) {
          actions.setPreContentSourceId(preContentSourceId);
          navigateToUrl((0, _routes.getSourcesPath)(`${(0, _routes.getAddPath)('github')}/configure${search}`, isOrganization));
        } else {
          setAddedSource(serviceName, indexPermissions, serviceType);
          navigateToUrl((0, _routes.getSourcesPath)(_routes.SOURCES_PATH, isOrganization));
        }
      } catch (e) {
        navigateToUrl((0, _routes.getSourcesPath)(_routes.SOURCES_PATH, isOrganization));
        (0, _flash_messages.flashAPIErrors)(e);
      }
    },
    setFirstStep: () => {
      const firstStep = getFirstStep(values.sourceConfigData, props.initialStep);
      actions.setAddSourceStep(firstStep);
    },
    createContentSource: async ({
      successCallback,
      errorCallback
    }) => {
      const {
        serviceType
      } = props;
      (0, _flash_messages.clearFlashMessages)();
      const {
        isOrganization
      } = _app_logic.AppLogic.values;
      const route = isOrganization ? '/internal/workplace_search/org/create_source' : '/internal/workplace_search/account/create_source';
      const {
        selectedGithubOrganizations: githubOrganizations,
        loginValue,
        passwordValue,
        indexPermissionsValue
      } = values;
      const params = {
        service_type: serviceType,
        login: loginValue || undefined,
        password: passwordValue || undefined,
        organizations: githubOrganizations.length > 0 ? githubOrganizations : undefined,
        index_permissions: indexPermissionsValue || undefined
      };

      // Remove undefined values from params
      Object.keys(params).forEach(key => params[key] === undefined && delete params[key]);
      try {
        await _http.HttpLogic.values.http.post(route, {
          body: JSON.stringify({
            ...params
          })
        });
        successCallback();
      } catch (e) {
        (0, _flash_messages.flashAPIErrors)(e);
        if (errorCallback) errorCallback();
      } finally {
        actions.setButtonNotLoading();
      }
    }
  })
});
exports.AddSourceLogic = AddSourceLogic;
const getFirstStep = (sourceConfigData, initialStep) => {
  const {
    configured
  } = sourceConfigData;
  if (initialStep === 'connect') return AddSourceSteps.ConnectInstanceStep;
  if (initialStep === 'configure') return AddSourceSteps.ConfigureOauthStep;
  if (initialStep === 'reauthenticate') return AddSourceSteps.ReauthenticateStep;
  if (configured) return AddSourceSteps.ConnectInstanceStep;
  return AddSourceSteps.SaveConfigStep;
};