"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.formatEjectPackagedAssetsSummary = formatEjectPackagedAssetsSummary;
exports.ejectPackagedAssets = ejectPackagedAssets;
const promises_1 = require("node:fs/promises");
const node_path_1 = __importDefault(require("node:path"));
const fs_errors_1 = require("./fs-errors");
function formatEjectPackagedAssetsSummary(input) {
    return [
        `${input.label} ejected to ${node_path_1.default.relative(input.cwd, input.result.targetDirectory) || "."}.`,
        `Created: ${input.result.createdPaths.length}`,
        `Skipped: ${input.result.skippedPaths.length}`,
        `Overwritten: ${input.result.overwrittenPaths.length}`,
    ].join("\n");
}
async function ejectPackagedAssets(options) {
    const sourceFiles = await listPackagedAssetFiles(options);
    if (sourceFiles.length === 0) {
        throw new Error(`No ${options.assetLabel} files found in ${options.sourceDirectory}.`);
    }
    const createdPaths = [];
    const overwrittenPaths = [];
    const skippedPaths = [];
    for (const sourceFile of sourceFiles) {
        const sourcePath = node_path_1.default.join(options.sourceDirectory, sourceFile);
        const targetPath = node_path_1.default.join(options.targetDirectory, sourceFile);
        const targetExists = await fileExists(targetPath);
        if (!options.force && targetExists) {
            skippedPaths.push(targetPath);
            continue;
        }
        await (0, promises_1.mkdir)(node_path_1.default.dirname(targetPath), { recursive: true });
        await (0, promises_1.copyFile)(sourcePath, targetPath);
        if (targetExists) {
            overwrittenPaths.push(targetPath);
        }
        else {
            createdPaths.push(targetPath);
        }
    }
    return {
        createdPaths,
        overwrittenPaths,
        skippedPaths,
        targetDirectory: options.targetDirectory,
    };
}
async function listPackagedAssetFiles(options) {
    let sourceFiles;
    try {
        sourceFiles = await listPackagedAssetFilesRecursive(options, "");
    }
    catch (error) {
        if ((0, fs_errors_1.isMissingFileError)(error)) {
            throw new Error(`No ${options.assetLabel} files found in ${options.sourceDirectory}.`);
        }
        throw error;
    }
    for (const sourceFile of sourceFiles) {
        validatePackagedAssetPath(sourceFile, options.invalidPathLabel);
    }
    return sourceFiles;
}
async function listPackagedAssetFilesRecursive(options, relativeDirectory) {
    const entries = await (0, promises_1.readdir)(node_path_1.default.join(options.sourceDirectory, relativeDirectory), {
        withFileTypes: true,
    });
    const files = await Promise.all(entries.map(async (entry) => {
        const relativePath = node_path_1.default.join(relativeDirectory, entry.name);
        if (entry.isDirectory()) {
            return listPackagedAssetFilesRecursive(options, relativePath);
        }
        return entry.isFile() &&
            entry.name.endsWith(options.fileExtension) &&
            (options.fileName === undefined || relativePath === options.fileName)
            ? [relativePath]
            : [];
    }));
    return files.flat().sort();
}
function validatePackagedAssetPath(relativePath, invalidPathLabel) {
    for (const segment of relativePath.split(node_path_1.default.sep)) {
        if (segment.startsWith("__")) {
            throw new Error(`Invalid ${invalidPathLabel} path: ${relativePath}. Path segments must not start with "__".`);
        }
    }
}
async function fileExists(filePath) {
    try {
        await (0, promises_1.access)(filePath);
        return true;
    }
    catch (error) {
        if ((0, fs_errors_1.isMissingFileError)(error)) {
            return false;
        }
        throw error;
    }
}
