"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.DocumentCreationLogic = void 0;
var _dedent = _interopRequireDefault(require("dedent"));
var _kea = require("kea");
var _lodash = require("lodash");
var _http = require("../../../shared/http");
var _engine = require("../engine");
var _constants = require("./constants");
var _types = require("./types");
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 DocumentCreationLogic = (0, _kea.kea)({
  path: ['enterprise_search', 'app_search', 'document_creation_logic'],
  actions: () => ({
    showCreationModes: () => null,
    openDocumentCreation: creationMode => ({
      creationMode
    }),
    closeDocumentCreation: () => null,
    setCreationStep: creationStep => ({
      creationStep
    }),
    setActiveJsonTab: activeJsonTab => ({
      activeJsonTab
    }),
    setTextInput: textInput => ({
      textInput
    }),
    setFileInput: fileInput => ({
      fileInput
    }),
    setWarnings: warnings => ({
      warnings
    }),
    setErrors: errors => ({
      errors
    }),
    setSummary: summary => ({
      summary
    }),
    onSubmitJson: () => null,
    onSubmitFile: () => null,
    uploadDocuments: ({
      documents
    }) => ({
      documents
    })
  }),
  reducers: () => ({
    isDocumentCreationOpen: [false, {
      showCreationModes: () => true,
      openDocumentCreation: () => true,
      closeDocumentCreation: () => false
    }],
    creationMode: ['api', {
      openDocumentCreation: (_, {
        creationMode
      }) => creationMode
    }],
    activeJsonTab: ['uploadTab', {
      setActiveJsonTab: (_, {
        activeJsonTab
      }) => activeJsonTab
    }],
    creationStep: [_types.DocumentCreationStep.AddDocuments, {
      showCreationModes: () => _types.DocumentCreationStep.ShowCreationModes,
      openDocumentCreation: () => _types.DocumentCreationStep.AddDocuments,
      setCreationStep: (_, {
        creationStep
      }) => creationStep
    }],
    textInput: [(0, _dedent.default)(_constants.DOCUMENTS_API_JSON_EXAMPLE), {
      setTextInput: (_, {
        textInput
      }) => textInput,
      closeDocumentCreation: () => (0, _dedent.default)(_constants.DOCUMENTS_API_JSON_EXAMPLE),
      setActiveJsonTab: () => (0, _dedent.default)(_constants.DOCUMENTS_API_JSON_EXAMPLE)
    }],
    fileInput: [null, {
      setFileInput: (_, {
        fileInput
      }) => fileInput,
      closeDocumentCreation: () => null,
      setActiveJsonTab: () => null
    }],
    isUploading: [false, {
      onSubmitFile: () => true,
      onSubmitJson: () => true,
      setErrors: () => false,
      setSummary: () => false,
      setActiveJsonTab: () => false
    }],
    warnings: [[], {
      onSubmitJson: () => [],
      setWarnings: (_, {
        warnings
      }) => warnings,
      closeDocumentCreation: () => [],
      setActiveJsonTab: () => []
    }],
    errors: [[], {
      onSubmitJson: () => [],
      setErrors: (_, {
        errors
      }) => Array.isArray(errors) ? errors : [errors],
      closeDocumentCreation: () => [],
      setActiveJsonTab: () => []
    }],
    summary: [{}, {
      setSummary: (_, {
        summary
      }) => summary
    }]
  }),
  listeners: ({
    values,
    actions
  }) => ({
    onSubmitFile: async () => {
      const {
        fileInput
      } = values;
      if (!fileInput) {
        return actions.setErrors([_constants.DOCUMENT_CREATION_ERRORS.NO_FILE]);
      }
      try {
        const textInput = await (0, _utils.readUploadedFileAsText)(fileInput);
        actions.setTextInput(textInput);
        actions.onSubmitJson();
      } catch {
        actions.setErrors([_constants.DOCUMENT_CREATION_ERRORS.NO_VALID_FILE]);
      }
    },
    onSubmitJson: () => {
      const {
        textInput
      } = values;
      const MAX_UPLOAD_BYTES = 50 * 1000000; // 50 MB
      if (Buffer.byteLength(textInput) > MAX_UPLOAD_BYTES) {
        actions.setWarnings([_constants.DOCUMENT_CREATION_WARNINGS.LARGE_FILE]);
      }
      let documents;
      try {
        documents = JSON.parse(textInput);
      } catch (error) {
        return actions.setErrors([error.message]);
      }
      if (Array.isArray(documents)) {
        actions.uploadDocuments({
          documents
        });
      } else if ((0, _lodash.isPlainObject)(documents)) {
        actions.uploadDocuments({
          documents: [documents]
        });
      } else {
        actions.setErrors([_constants.DOCUMENT_CREATION_ERRORS.NOT_VALID]);
      }
    },
    uploadDocuments: async ({
      documents
    }) => {
      const {
        http
      } = _http.HttpLogic.values;
      const {
        engineName
      } = _engine.EngineLogic.values;
      const CHUNK_SIZE = 100;
      const MAX_EXAMPLES = 5;
      const promises = (0, _lodash.chunk)(documents, CHUNK_SIZE).map(documentsChunk => {
        const body = JSON.stringify({
          documents: documentsChunk
        });
        return http.post(`/internal/app_search/engines/${engineName}/documents`, {
          body
        });
      });
      try {
        const responses = await Promise.all(promises);
        const summary = {
          errors: [],
          validDocuments: {
            total: 0,
            examples: []
          },
          invalidDocuments: {
            total: 0,
            examples: []
          },
          newSchemaFields: []
        };
        responses.forEach(response => {
          var _response$errors;
          if (((_response$errors = response.errors) === null || _response$errors === void 0 ? void 0 : _response$errors.length) > 0) {
            summary.errors = (0, _lodash.uniq)([...summary.errors, ...response.errors]);
            return;
          }
          summary.validDocuments.total += response.validDocuments.total;
          summary.invalidDocuments.total += response.invalidDocuments.total;
          summary.validDocuments.examples = [...summary.validDocuments.examples, ...response.validDocuments.examples].slice(0, MAX_EXAMPLES);
          summary.invalidDocuments.examples = [...summary.invalidDocuments.examples, ...response.invalidDocuments.examples].slice(0, MAX_EXAMPLES);
          summary.newSchemaFields = (0, _lodash.uniq)([...summary.newSchemaFields, ...response.newSchemaFields]);
        });
        if (summary.errors.length > 0) {
          actions.setErrors(summary.errors);
        } else {
          actions.setSummary(summary);
          actions.setCreationStep(_types.DocumentCreationStep.ShowSummary);
        }
      } catch ({
        body,
        message
      }) {
        const errors = body ? `[${body.statusCode} ${body.error}] ${body.message}` : message;
        actions.setErrors(errors);
      }
    }
  })
});
exports.DocumentCreationLogic = DocumentCreationLogic;