"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.deprecate = void 0;
exports.stringify = stringify;
exports.prepareFile = prepareFile;
exports.prepareFiles = prepareFiles;
exports.streamToBuffer = streamToBuffer;
const node_fs_1 = require("node:fs");
const node_path_1 = __importDefault(require("node:path"));
const node_util_1 = __importDefault(require("node:util"));
const errors_js_1 = require("./errors.cjs");
const file_type_js_1 = require("./internal/file-type.cjs");
const mime_js_1 = require("./internal/mime.cjs");
/**
 * Stable JSON-serializer used to convert structured Telegram options
 * (entities, reply_markup, reply_parameters, etc.) into the string form
 * the Bot API expects on x-www-form-urlencoded / multipart bodies.
 *
 * Strings are passed through unchanged so callers may opt into
 * pre-serialized payloads.
 */
function stringify(data) {
    if (typeof data === "string")
        return data;
    return JSON.stringify(data);
}
/**
 * Lightweight `util.deprecate` wrapper. Logs each unique message exactly once.
 */
exports.deprecate = (() => {
    const issued = new Set();
    return (msg) => {
        if (issued.has(msg))
            return;
        issued.add(msg);
        node_util_1.default.deprecate(() => { }, msg, "node-telegram-bot-api")();
    };
})();
/**
 * Best-effort filename extraction from a stream's `path` (when the stream
 * was created via `fs.createReadStream`).
 */
function filenameFromStream(stream) {
    const maybe = stream.path;
    if (!maybe)
        return undefined;
    return node_path_1.default.basename(typeof maybe === "string" ? maybe : maybe.toString());
}
function isReadable(value) {
    return (!!value &&
        typeof value === "object" &&
        !Buffer.isBuffer(value) &&
        typeof value.pipe === "function");
}
/**
 * Format an arbitrary file-like input into:
 *   - a {@link PreparedFile} (multipart upload)         OR
 *   - a string `fileId` / URL (no upload necessary)
 *
 * @param data           the user-supplied value (path, buffer, stream, or fileId/URL)
 * @param meta           optional filename / content type hints
 * @param filepathLookup whether to treat strings as filesystem paths (mirrors
 *                       legacy `options.filepath`).
 */
async function prepareFile(data, meta = {}, filepathLookup = true) {
    if (data === undefined || data === null) {
        return { file: null, fileId: null };
    }
    let { filename, contentType } = meta;
    if (Buffer.isBuffer(data)) {
        if (!contentType) {
            const detected = (0, file_type_js_1.detectFileType)(data);
            if (detected) {
                contentType = detected.mime;
                if (!filename)
                    filename = `data.${detected.ext}`;
            }
        }
        filename = filename ?? "file";
        contentType = contentType ?? (0, mime_js_1.lookupMime)(filename) ?? "application/octet-stream";
        return { file: { value: data, filename, contentType }, fileId: null };
    }
    if (isReadable(data)) {
        if (!filename)
            filename = filenameFromStream(data) ?? "file";
        contentType = contentType ?? (0, mime_js_1.lookupMime)(filename) ?? "application/octet-stream";
        return { file: { value: data, filename, contentType }, fileId: null };
    }
    if (typeof data === "string") {
        if (filepathLookup && (0, node_fs_1.existsSync)(data)) {
            const stream = (0, node_fs_1.createReadStream)(data);
            filename = filename ?? node_path_1.default.basename(data);
            contentType = contentType ?? (0, mime_js_1.lookupMime)(filename) ?? "application/octet-stream";
            return { file: { value: stream, filename, contentType }, fileId: null };
        }
        // Treat as fileId or already-public URL.
        return { file: null, fileId: data };
    }
    throw new errors_js_1.FatalError(`Unsupported file input: ${typeof data}`);
}
/**
 * Variant for multi-file methods (sendMediaGroup, sendPaidMedia, postStory, …).
 */
async function prepareFiles(attachKey, inputs, defaultMeta = {}, filepathLookup = true) {
    const formData = {};
    const fileIds = {};
    for (let index = 0; index < inputs.length; index++) {
        const item = inputs[index];
        const value = item.media ?? item.data;
        const meta = { ...defaultMeta, ...item.fileOptions };
        const { file, fileId } = await prepareFile(value, meta, filepathLookup);
        if (file) {
            formData[`${attachKey}_${index}`] = file;
        }
        else if (fileId !== null) {
            fileIds[index] = fileId;
        }
    }
    return { formData, fileIds };
}
/**
 * Read a Node.js stream into a Buffer.
 */
async function streamToBuffer(stream) {
    const chunks = [];
    for await (const chunk of stream) {
        chunks.push(typeof chunk === "string" ? Buffer.from(chunk) : chunk);
    }
    return Buffer.concat(chunks);
}
//# sourceMappingURL=utils.cjs.map