"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.command = void 0;
const clc = require("colorette");
const functionsConfig = require("../functionsConfig");
const command_1 = require("../command");
const error_1 = require("../error");
const projectUtils_1 = require("../projectUtils");
const prompt_1 = require("../prompt");
const functional_1 = require("../functional");
const requirePermissions_1 = require("../requirePermissions");
const helper = require("../deploy/functions/functionsDeployHelper");
const utils = require("../utils");
const backend = require("../deploy/functions/backend");
const planner = require("../deploy/functions/release/planner");
const fabricator = require("../deploy/functions/release/fabricator");
const executor = require("../deploy/functions/release/executor");
const reporter = require("../deploy/functions/release/reporter");
const containerCleaner = require("../deploy/functions/containerCleaner");
const getProjectNumber_1 = require("../getProjectNumber");
exports.command = new command_1.Command("functions:delete [filters...]")
    .description("delete one or more Cloud Functions by name or group name.")
    .option("--region <region>", "Specify region of the function to be deleted. " +
    "If omitted, functions from all regions whose names match the filters will be deleted. ")
    .withForce()
    .before(requirePermissions_1.requirePermissions, ["cloudfunctions.functions.list", "cloudfunctions.functions.delete"])
    .action(async (filters, options) => {
    if (!filters.length) {
        return utils.reject("Must supply at least function or group name.");
    }
    const context = {
        projectId: (0, projectUtils_1.needProjectId)(options),
        filters: filters.map((f) => ({ idChunks: f.split(/[-.]/) })),
    };
    const [config, existingBackend] = await Promise.all([
        functionsConfig.getFirebaseConfig(options),
        backend.existingBackend(context),
    ]);
    await backend.checkAvailability(context, backend.empty());
    const appEngineLocation = functionsConfig.getAppEngineLocation(config);
    if (options.region) {
        existingBackend.endpoints = { [options.region]: existingBackend.endpoints[options.region] };
    }
    const plan = planner.createDeploymentPlan({
        wantBackend: backend.empty(),
        haveBackend: existingBackend,
        codebase: "",
        filters: context.filters,
        deleteAll: true,
    });
    const allEpToDelete = Object.values(plan)
        .map((changes) => changes.endpointsToDelete)
        .reduce(functional_1.reduceFlat, [])
        .sort(backend.compareFunctions);
    if (allEpToDelete.length === 0) {
        throw new error_1.FirebaseError(`The specified filters do not match any existing functions in project ${clc.bold(context.projectId)}.`);
    }
    const deleteList = allEpToDelete.map((func) => `\t${helper.getFunctionLabel(func)}`).join("\n");
    const confirmDeletion = await (0, prompt_1.promptOnce)({
        type: "confirm",
        name: "force",
        default: false,
        message: "You are about to delete the following Cloud Functions:\n" +
            deleteList +
            "\n  Are you sure?",
    }, options);
    if (!confirmDeletion) {
        throw new error_1.FirebaseError("Command aborted.");
    }
    const functionExecutor = new executor.QueueExecutor({
        retries: 30,
        backoff: 20000,
        concurrency: 40,
        maxBackoff: 40000,
    });
    try {
        const fab = new fabricator.Fabricator({
            functionExecutor,
            appEngineLocation,
            executor: new executor.QueueExecutor({}),
            sources: {},
            projectNumber: options.projectNumber || (await (0, getProjectNumber_1.getProjectNumber)({ projectId: context.projectId })),
        });
        const summary = await fab.applyPlan(plan);
        await reporter.logAndTrackDeployStats(summary);
        reporter.printErrors(summary);
    }
    catch (err) {
        throw new error_1.FirebaseError("Failed to delete functions", {
            original: err,
            exit: 1,
        });
    }
    await containerCleaner.cleanupBuildImages([], allEpToDelete);
});
