/**
 * This file is part of the NocoBase (R) project.
 * Copyright (c) 2020-2024 NocoBase Co., Ltd.
 * Authors: NocoBase Team.
 *
 * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
 * For more information, please refer to: https://www.nocobase.com/agreement.
 */

var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
  // If the importer is in node compatibility mode or this is not an ESM
  // file that has been converted to a CommonJS file using a Babel-
  // compatible transform (i.e. "__esModule" has not been set), then set
  // "default" to the CommonJS "module.exports" for node compatibility.
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
  mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var cached_exports = {};
__export(cached_exports, {
  CachedDocumentLoader: () => CachedDocumentLoader
});
module.exports = __toCommonJS(cached_exports);
var import_promises = __toESM(require("node:fs/promises"));
var import_node_os = __toESM(require("node:os"));
var import_node_path = __toESM(require("node:path"));
var import_documents = require("@langchain/core/documents");
var import_constants = require("./constants");
var import_utils = require("./utils");
class CachedDocumentLoader {
  constructor(plugin, options) {
    this.plugin = plugin;
    this.options = options;
  }
  async load(file) {
    const sourceFile = this.toPlainObject(file);
    if (!this.options.supports(sourceFile)) {
      return {
        supported: false,
        fromCache: false,
        text: "",
        documents: [],
        meta: {
          sourceFileId: sourceFile.id
        }
      };
    }
    if (sourceFile.size === 0) {
      return {
        supported: true,
        fromCache: false,
        text: "",
        documents: [],
        meta: {
          sourceFileId: sourceFile.id
        }
      };
    }
    const cached = await this.loadFromCache(sourceFile);
    if (cached) {
      return cached;
    }
    try {
      const documents = await this.options.loader.load(sourceFile);
      const text = this.documentsToText(documents);
      const parsedFile = await this.persistParsedText(sourceFile, text);
      await this.updateSourceMeta(sourceFile, {
        status: "ready",
        parserVersion: this.options.parserVersion,
        parsedFileId: parsedFile.id,
        parsedFilename: parsedFile.filename,
        parsedMimetype: this.options.parsedMimetype,
        updatedAt: (/* @__PURE__ */ new Date()).toISOString()
      });
      return {
        supported: true,
        fromCache: false,
        text,
        documents,
        meta: {
          sourceFileId: sourceFile.id,
          parsedFileId: parsedFile.id
        }
      };
    } catch (error) {
      await this.updateSourceMeta(sourceFile, {
        status: "failed",
        parserVersion: this.options.parserVersion,
        updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
        error: (error == null ? void 0 : error.message) ?? String(error)
      });
      throw error;
    }
  }
  async loadFromCache(sourceFile) {
    const meta = this.getParseMeta(sourceFile.meta);
    if (!meta || meta.status !== "ready" || meta.parserVersion !== this.options.parserVersion || !meta.parsedFileId) {
      return null;
    }
    const parsedModel = await this.aiFilesRepo.findById(meta.parsedFileId);
    if (!parsedModel) {
      return null;
    }
    const parsedFile = this.toPlainObject(parsedModel);
    const text = await this.readTextFile(parsedFile);
    const extname = (0, import_utils.resolveExtname)(sourceFile);
    const documents = this.toDocumentsFromText(text, sourceFile, extname);
    return {
      supported: true,
      fromCache: true,
      text,
      documents,
      meta: {
        sourceFileId: sourceFile.id,
        parsedFileId: parsedFile.id
      }
    };
  }
  async persistParsedText(sourceFile, text) {
    const tempFilePath = import_node_path.default.join(
      import_node_os.default.tmpdir(),
      `${sourceFile.id ?? Date.now()}.${Date.now()}.parsed.${this.options.parsedFileExtname}`
    );
    await import_promises.default.writeFile(tempFilePath, text, "utf-8");
    try {
      const storageName = await this.resolveStorageName(sourceFile);
      const created = await this.fileManager.createFileRecord({
        collectionName: "aiFiles",
        filePath: tempFilePath,
        storageName,
        values: {
          title: `${sourceFile.title ?? sourceFile.filename ?? "document"} (parsed)`,
          mimetype: this.options.parsedMimetype,
          meta: {
            parserVersion: this.options.parserVersion,
            sourceFileId: sourceFile.id
          }
        }
      });
      return this.toPlainObject(created);
    } finally {
      await import_promises.default.rm(tempFilePath, { force: true });
    }
  }
  async updateSourceMeta(sourceFile, documentParse) {
    if (!sourceFile.id) {
      return;
    }
    const nextMeta = {
      ...sourceFile.meta ?? {},
      [import_constants.DOCUMENT_PARSE_META_KEY]: documentParse
    };
    await this.aiFilesRepo.update({
      filter: {
        id: sourceFile.id
      },
      values: {
        meta: nextMeta
      }
    });
  }
  async resolveStorageName(file) {
    if (!file.storageId) {
      return void 0;
    }
    if (!this.fileManager.storagesCache.size) {
      await this.fileManager.loadStorages();
    }
    const storage = this.fileManager.storagesCache.get(file.storageId);
    return storage == null ? void 0 : storage.name;
  }
  async readTextFile(file) {
    const { stream } = await this.fileManager.getFileStream(file);
    const chunks = [];
    for await (const chunk of stream) {
      chunks.push(chunk);
    }
    return Buffer.concat(chunks).toString("utf-8");
  }
  documentsToText(documents) {
    return documents.map((doc) => doc.pageContent).join("\n\n");
  }
  toDocumentsFromText(text, sourceFile, extname) {
    if (!text) {
      return [];
    }
    return [
      new import_documents.Document({
        pageContent: text,
        metadata: {
          source: sourceFile.filename,
          extname
        }
      })
    ];
  }
  getParseMeta(meta) {
    if (!meta || typeof meta !== "object") {
      return null;
    }
    return meta[import_constants.DOCUMENT_PARSE_META_KEY] ?? null;
  }
  toPlainObject(file) {
    if (file == null ? void 0 : file.toJSON) {
      return file.toJSON();
    }
    return file;
  }
  get aiFilesRepo() {
    return this.plugin.db.getRepository("aiFiles");
  }
  get fileManager() {
    return this.plugin.app.pm.get("file-manager");
  }
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  CachedDocumentLoader
});
