"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
    for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.guid6 = void 0;
exports.compressToZip = compressToZip;
exports.downloadAndExtractRemoteZip = downloadAndExtractRemoteZip;
exports.getRuntime = getRuntime;
exports.getEnvVar = getEnvVar;
exports.rsaEncrypt = rsaEncrypt;
exports.sleep = sleep;
exports.upperCaseStringFisrt = upperCaseStringFisrt;
exports.upperCaseObjKey = upperCaseObjKey;
exports.fetchTemplates = fetchTemplates;
const archiver_1 = __importDefault(require("archiver"));
const crypto_1 = __importDefault(require("crypto"));
const fs_extra_1 = __importDefault(require("fs-extra"));
const lodash_1 = __importDefault(require("lodash"));
const path_1 = __importDefault(require("path"));
const unzipper_1 = __importDefault(require("unzipper"));
const constant_1 = require("../constant");
const http_request_1 = require("./http-request");
__exportStar(require("./auth"), exports);
__exportStar(require("./cloud-api-request"), exports);
__exportStar(require("./cloudbase-request"), exports);
__exportStar(require("./envLazy"), exports);
__exportStar(require("./fs"), exports);
__exportStar(require("./http-request"), exports);
var uuid_1 = require("./uuid");
Object.defineProperty(exports, "guid6", { enumerable: true, get: function () { return uuid_1.guid6; } });
async function compressToZip(option) {
    const { dirPath, outputPath, ignore, pattern = '**/*' } = option;
    return new Promise((resolve, reject) => {
        const output = fs_extra_1.default.createWriteStream(outputPath);
        const archive = (0, archiver_1.default)('zip');
        output.on('close', function () {
            resolve({
                zipPath: outputPath,
                size: Math.ceil(archive.pointer() / 1024)
            });
        });
        archive.on('error', function (err) {
            reject(err);
        });
        archive.pipe(output);
        // append files from a glob pattern
        archive.glob(pattern, {
            // 目标路径
            cwd: dirPath,
            ignore: ignore,
            dot: true
        });
        archive.finalize();
    });
}
/**
 * 下载并解压云托管模板到指定目录
 * @param {string} downloadUrl 模板下载地址
 * @param {string} targetPath 目标路径
 * @returns {Promise<void>}
 * @throws 当下载失败或解压失败时抛出错误
 */
async function downloadAndExtractRemoteZip(downloadUrl, targetPath) {
    const downloadResponse = await (0, http_request_1.fetchStream)(downloadUrl);
    if (!downloadResponse.ok) {
        throw new Error(`下载失败，状态码: ${downloadResponse.status}`);
    }
    if (!downloadResponse.body) {
        throw new Error('下载响应中没有数据流');
    }
    // 创建目标目录
    const dirPath = path_1.default.resolve(targetPath);
    await fs_extra_1.default.ensureDir(dirPath);
    // 使用流式解压，避免大文件内存问题
    await new Promise((resolve, reject) => {
        let fileCount = 0;
        let extractedCount = 0;
        downloadResponse
            .body.pipe(unzipper_1.default.Parse())
            .on('error', reject)
            .on('entry', async (entry) => {
            const filePath = path_1.default.join(dirPath, entry.path);
            try {
                // 确保父目录存在（处理嵌套目录情况）
                await fs_extra_1.default.ensureDir(path_1.default.dirname(filePath));
                // 如果是目录则创建，否则写入文件
                if (entry.type === 'Directory') {
                    await fs_extra_1.default.ensureDir(filePath);
                    extractedCount++;
                }
                else {
                    fileCount++;
                    entry
                        .pipe(fs_extra_1.default.createWriteStream(filePath))
                        .on('error', reject)
                        .on('finish', () => {
                        extractedCount++;
                        checkCompletion();
                    });
                }
            }
            catch (err) {
                reject(err);
            }
        })
            .on('close', checkCompletion);
        function checkCompletion() {
            if (fileCount > 0 && fileCount === extractedCount) {
                resolve('');
            }
        }
    });
}
function getRuntime() {
    return process.env[constant_1.ENV_NAME.ENV_RUNENV];
}
function getEnvVar(envName) {
    return process.env[envName];
}
function rsaEncrypt(data) {
    const buffer = Buffer.from(data);
    const encrypted = crypto_1.default.publicEncrypt({
        key: constant_1.PUBLIC_RSA_KEY,
        padding: crypto_1.default.constants.RSA_PKCS1_PADDING
    }, buffer);
    return encrypted.toString('base64');
}
function sleep(time) {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve();
        }, time);
    });
}
function upperCaseStringFisrt(str) {
    return str.slice(0, 1).toUpperCase().concat(str.slice(1));
}
function upperCaseObjKey(object) {
    const type = Object.prototype.toString.call(object).slice(8, -1);
    if (type === 'Object') {
        let newObj = {};
        // eslint-disable-next-line guard-for-in
        for (let key in object) {
            newObj[upperCaseStringFisrt(key)] = upperCaseObjKey(object[key]);
        }
        return newObj;
    }
    if (type === 'Array') {
        let newArr = [];
        for (let item of object) {
            newArr.push(upperCaseObjKey(item));
        }
        return newArr;
    }
    return object;
}
/**
 * 获取函数模板列表
 * @param type 函数模板类型，支持 'scfFunc' 和 'tcbrFunc'
 * @returns
 */
async function fetchTemplates(types) {
    const apiUrl = 'https://qcloud-tcb-console-1258344699.ap-shanghai.service.tcloudbase.com/func_tpl/v1.0/function_list/find?skip=0&limit=500';
    const responseData = await (0, http_request_1.fetch)(apiUrl, {
        method: 'POST'
    });
    return responseData.data.filter((item) => lodash_1.default.intersection(types, item.funcTypes).length > 0);
}
