import { requiredOrgFlagWithDeprecations, SfCommand, } from "@salesforce/sf-plugins-core";
import { Flags } from "@salesforce/sf-plugins-core";
import { SfError, Messages } from "@salesforce/core";
import { soqlQuery, soqlQueryTooling, } from "../../../../common/utils/apiUtils.js";
import { execCommand, uxLog, uxLogTable } from "../../../../common/utils/index.js";
import { prompts } from "../../../../common/utils/prompts.js";
import c from "chalk";
import path from "path";
import fs from "fs";
import * as fsExtra from "fs-extra";
Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
const messages = Messages.loadMessages("sfdx-hardis", "org");
import { parseXmlFile, writeXmlFile, } from "../../../../common/utils/xmlUtils.js";
import { MetadataUtils } from "../../../../common/metadata-utils/index.js";
// Constants
const ALLOWED_AUTOMATIONS = ["Flow", "Trigger", "VR"];
const CREDITS_TEXT = "by sfdx-hardis : https://sfdx-hardis.cloudity.com/hardis/project/generate/bypass/";
const STATUS = {
    ADDED: "added",
    SKIPPED: "skipped",
    IGNORED: "ignored",
    FAILED: "failed",
};
export default class HardisProjectGenerateBypass extends SfCommand {
    skipCredits = false;
    retrieveFromOrg;
    static flags = {
        "target-org": requiredOrgFlagWithDeprecations,
        objects: Flags.string({
            aliases: ["sObjects"],
            char: "s",
            description: "Comma-separated list of sObjects to bypass (e.g., Account,Contact,Opportunity). If omitted, you will be prompted to select.",
            required: false,
        }),
        automations: Flags.string({
            char: "a",
            description: `Comma-separated automations to bypass: ${ALLOWED_AUTOMATIONS.join(", ")}`,
            required: false,
        }),
        websocket: Flags.string({
            description: messages.getMessage("websocket"),
        }),
        skipauth: Flags.boolean({
            description: "Skip authentication check when a default username is required",
        }),
        "skip-credits": Flags.boolean({
            aliases: ["skipCredits"],
            char: "k",
            description: 'Omit the "Generated by" line in the XML files',
            required: false,
            default: false,
        }),
        "apply-to-vrs": Flags.boolean({
            aliases: ["applyToVrs"],
            description: "Apply bypass to Validation Rules",
            required: false,
            default: false,
        }),
        "apply-to-triggers": Flags.boolean({
            aliases: ["applyToTriggers"],
            description: "Apply bypass to Triggers",
            required: false,
            default: false,
        }),
        "metadata-source": Flags.string({
            char: "r",
            aliases: ["metadataSource"],
            description: "Source of metadata elements to apply bypass to. Options: 'org' or 'local'.",
            required: false,
        }),
    };
    static description = `
## Command Behavior

**Generates custom permissions and permission sets to bypass specified Salesforce automations (Flows, Triggers, and Validation Rules) for specific sObjects.**

This command provides a controlled mechanism to temporarily or permanently disable automations for certain sObjects, which is invaluable for:

- **Data Loading:** Bypassing validation rules or triggers during large data imports.
- **Troubleshooting:** Isolating automation issues by temporarily disabling them.
- **Development:** Allowing developers to work on specific sObjects without triggering complex automations.

Key functionalities:

- **sObject Selection:** You can specify a comma-separated list of sObjects to bypass (e.g., \`Account,Contact\`). If omitted, an interactive prompt will allow you to select from available sObjects.
- **Automation Type Selection:** Choose which types of automations to bypass: \`Flow\`, \`Trigger\`, or \`VR\` (Validation Rules). If omitted, an interactive prompt will guide your selection.
- **Automatic Bypass Application:** Optionally, the command can automatically inject bypass logic into Validation Rules and Triggers. This involves modifying the Apex code for Triggers and the XML for Validation Rules.
- **Metadata Source:** You can choose to retrieve the metadata elements (Validation Rules, Triggers) from the org (\`--metadata-source org\`) or use local files (\`--metadata-source local\`). Retrieving from the org is recommended for accuracy.
- **Custom Permission and Permission Set Generation:** For each selected sObject and automation type, it generates:
  - A **Custom Permission** (e.g., \`BypassAccountFlows\`) that acts as the bypass switch.
  - A **Permission Set** (e.g., \`BypassAccountFlows\`) that grants the generated Custom Permission.
- **Credits Inclusion:** By default, generated XML files include a comment indicating they were generated by sfdx-hardis. This can be skipped using \`--skip-credits\`.

<details markdown="1">
<summary>Technical explanations</summary>

The command's technical implementation involves:

- **SOQL Queries (Tooling API):** It queries \`EntityDefinition\` to list customizable sObjects and \`ValidationRule\` and \`ApexTrigger\` to find existing automations.
- **Interactive Prompts:** Uses the \`prompts\` library to guide the user through selecting sObjects, automation types, and bypass application options.
- **XML Generation:** Dynamically generates XML content for Custom Permissions and Permission Sets, including descriptions and labels that clearly indicate their purpose.
- **File System Operations:** Uses \`fs-extra\` to create directories and write the generated Custom Permission and Permission Set XML files.
- **Metadata Retrieval (for Bypass Application):** If \`apply-to-vrs\` or \`apply-to-triggers\` is used and \`metadata-source\` is \`org\`, it retrieves the relevant Validation Rule or Apex Trigger metadata from the org using \`sf project retrieve start\`.
- **XML/Apex Code Modification:**
  - For Validation Rules, it modifies the \`errorConditionFormula\` in the XML to include a check for the bypass Custom Permission.
  - For Apex Triggers, it injects an \`if\` statement at the beginning of the trigger body to check for the bypass Custom Permission.
- **\`parseXmlFile\` and \`writeXmlFile\`:** Used for reading and writing XML metadata files.
- **\`execCommand\`:** Used for executing Salesforce CLI commands, particularly for metadata retrieval.
- **Error Handling:** Includes checks for invalid sObject or automation selections and provides informative error messages.
</details>
`;
    static examples = [
        "$ sf hardis:project:generate:bypass",
        "$ sf hardis:project:generate:bypass --sObjects Account,Contact,Opportunity",
        "$ sf hardis:project:generate:bypass --automations Flow,Trigger,VR",
        "$ sf hardis:project:generate:bypass --sObjects Account,Opportunity --automations Flow,Trigger",
        "$ sf hardis:project:generate:bypass --skipCredits",
        "$ sf hardis:project:generate:bypass --apply-to-vrs",
        "$ sf hardis:project:generate:bypass --apply-to-triggers",
        "$ sf hardis:project:generate:bypass --metadata-source org",
    ];
    // Main run method
    async run() {
        // Collect options
        const { flags } = await this.parse(HardisProjectGenerateBypass);
        const connection = flags["target-org"].getConnection();
        if (flags["metadata-source"] !== undefined &&
            flags["metadata-source"] !== null) {
            this.retrieveFromOrg =
                String(flags["metadata-source"]).trim().toLowerCase() === "org";
        }
        this.skipCredits = flags["skip-credits"] || false;
        let applyToTriggers = flags["apply-to-triggers"] || null;
        let applyToVrs = flags["apply-to-vrs"] || null;
        const sObjects = flags.objects || null;
        const automations = flags.automations || null;
        const availableSObjects = await this.getFilteredSObjects(connection);
        let targetSObjects = {};
        let targetAutomations = [];
        // Filter objects
        if (sObjects) {
            const sObjectsFromFlag = flags.sObjects.split(",").map((s) => s.trim());
            targetSObjects = Object.fromEntries(Object.entries(availableSObjects).filter(([key]) => {
                const res = sObjectsFromFlag.includes(key);
                if (!res) {
                    uxLog("warning", this, c.yellow(`Warning: sObject "${key}" is not available or not customizable. Skipping.`));
                }
                return res;
            }));
        }
        if (automations) {
            targetAutomations = automations
                .split(",")
                .map((s) => s.trim())
                .filter((s) => ALLOWED_AUTOMATIONS.includes(s));
        }
        // Generate global bypasses
        uxLog("action", this, c.cyan(`Generating global bypasses...`));
        this.generateFiles({ All: "All" }, ALLOWED_AUTOMATIONS);
        // Handle prompts if needed
        const promptsNeeded = [];
        if (!Object.keys(targetSObjects).length) {
            promptsNeeded.push({
                type: "multiselect",
                name: "sobjects",
                message: "Select sObjects for bypass",
                description: "Choose which sObjects should have automation bypass functionality",
                choices: Object.entries(availableSObjects).map(([devName, label]) => ({
                    title: label,
                    value: devName,
                })),
            });
        }
        if (!targetAutomations.length) {
            promptsNeeded.push({
                type: "multiselect",
                name: "automations",
                message: "Select automations to bypass",
                description: "Choose which types of automation should be bypassed",
                choices: ALLOWED_AUTOMATIONS.map((a) => ({ title: a, value: a })),
            });
        }
        if (applyToVrs == null && applyToTriggers == null) {
            promptsNeeded.push({
                type: "multiselect",
                name: "applyTo",
                message: "To which automations do you want to automatically apply the bypass?",
                description: "Select which automation types should have automatic bypass logic applied",
                choices: [
                    { title: "Validation Rules", value: "applyToVrs" },
                    { title: "Triggers", value: "applyToTriggers" },
                ],
            });
        }
        if (this.retrieveFromOrg == undefined || this.retrieveFromOrg == null) {
            promptsNeeded.push({
                type: "select",
                name: "elementSource",
                message: "Where do you want to get the elements to apply bypass to?",
                description: "Choose the source for retrieving automation elements",
                placeholder: "Select source",
                choices: [
                    { title: "Retrieve from org (recommended)", value: "org" },
                    { title: "Use local elements in the project", value: "local" },
                ],
            });
        }
        if (promptsNeeded.length) {
            const promptResults = await prompts(promptsNeeded);
            if (promptResults.sobjects) {
                targetSObjects = Object.fromEntries(Object.entries(availableSObjects).filter(([key]) => promptResults.sobjects.includes(key)));
            }
            if (promptResults.automations) {
                targetAutomations = promptResults.automations;
            }
            if (!applyToTriggers) {
                applyToTriggers = promptResults.applyTo?.includes("applyToTriggers");
            }
            if (!applyToVrs) {
                applyToVrs = promptResults.applyTo?.includes("applyToVrs");
            }
            if (promptResults.elementSource) {
                this.retrieveFromOrg = promptResults.elementSource === "org";
            }
        }
        // Validate selections
        if (!Object.keys(targetSObjects).length) {
            throw new SfError(c.red("ERROR: You must select at least one sObject."));
        }
        if (!targetAutomations.length) {
            throw new SfError(c.red("ERROR: You must select at least one automation type."));
        }
        // Generate files and apply bypasses
        uxLog("action", this, c.cyan(`Generating bypass files for selected sObjects and automations...`));
        this.generateFiles(targetSObjects, targetAutomations);
        if (applyToVrs) {
            uxLog("action", this, c.cyan(`Applying bypass to Validation Rules...`));
            await this.applyBypassToValidationRules(connection, targetSObjects);
        }
        if (applyToTriggers) {
            uxLog("action", this, c.cyan(`Applying bypass to Triggers...`));
            await this.applyBypassToTriggers(connection, targetSObjects);
        }
        return {
            outputString: "Generated bypass custom permissions and permission sets",
        };
    }
    // Query methods
    async querySObjects(connection) {
        const sObjectsQuery = `
    Select Id, Label, DeveloperName, QualifiedApiName, DurableId, IsTriggerable, IsCustomizable, IsApexTriggerable 
      FROM EntityDefinition WHERE IsTriggerable = true AND IsCustomizable = true and IsCustomSetting = false ORDER BY DeveloperName`;
        const results = await soqlQuery(sObjectsQuery, connection);
        uxLog("log", this, c.grey(`Found ${results.records.length} sObjects.`));
        return results;
    }
    async getFilteredSObjects(connection) {
        const sObjectResults = await this.querySObjects(connection);
        const sObjectsDict = {};
        for (const record of sObjectResults.records) {
            if (!record.DeveloperName.endsWith("__Share") &&
                !record.DeveloperName.endsWith("__ChangeEvent")) {
                sObjectsDict[record.DeveloperName] = `${record.Label} (${record.QualifiedApiName})`;
            }
        }
        return sObjectsDict;
    }
    async queryTriggers(connection) {
        const query = `SELECT Id, Name, Status, IsValid, Body, BodyCrc, TableEnumOrId, ManageableState From ApexTrigger WHERE ManageableState != 'installed'`;
        const results = await soqlQueryTooling(query, connection);
        uxLog("log", this, c.grey(`Found ${results.records.length} Triggers.`));
        return results;
    }
    filterTriggerResults(triggerResults, sObjects) {
        return triggerResults.records.filter((trigger) => {
            const sObjectApiNameWithoutC = trigger.TableEnumOrId?.replace("__c", "");
            return (sObjectApiNameWithoutC &&
                Object.keys(sObjects).includes(sObjectApiNameWithoutC) &&
                trigger.Body != "(hidden)");
        });
    }
    async queryValidationRules(connection, sObjects) {
        const query = `SELECT ValidationName, EntityDefinition.QualifiedApiName, ManageableState FROM ValidationRule 
      WHERE ManageableState != 'installed' AND EntityDefinition.DeveloperName IN (${Object.keys(sObjects)
            .map((s) => `'${s}'`)
            .join(", ")})`;
        const results = await soqlQueryTooling(query, connection);
        uxLog("log", this, c.grey(`Found ${results.records.length} Validation Rules.`));
        return results;
    }
    // XML Generation
    generateXML(type, sObject, automation) {
        const creditsText = this.skipCredits ? "" : `Generated ${CREDITS_TEXT}`;
        if (type === "customPermission") {
            return `<?xml version="1.0" encoding="UTF-8"?>
  <CustomPermission xmlns="http://soap.sforce.com/2006/04/metadata">
    <isLicensed>false</isLicensed>
    <label>Bypass ${automation}s for ${sObject}</label>
    <description>If assigned (through a Permission Set), this Custom Permission will disable the execution of ${automation}s defined on the ${sObject} sObject.${creditsText}</description>
  </CustomPermission>`;
        }
        else {
            return `<?xml version="1.0" encoding="UTF-8"?>
  <PermissionSet xmlns="http://soap.sforce.com/2006/04/metadata">
    <customPermissions>
        <enabled>true</enabled>
        <name>Bypass${sObject}${automation}s</name>
    </customPermissions>
    <hasActivationRequired>false</hasActivationRequired>
    <label>Bypass ${automation}s for ${sObject}</label>
    <description>If assigned, this Permission Set will disable the execution of ${automation}s defined on the ${sObject} sObject.${creditsText}</description>
  </PermissionSet>`;
        }
    }
    generateXMLFiles(sObject, automation) {
        const customPermissionFile = path.join(`force-app/main/default/customPermissions/Bypass${sObject}${automation}s.customPermission-meta.xml`);
        const permissionSetFile = path.join(`force-app/main/default/permissionsets/Bypass${sObject}${automation}s.permissionset-meta.xml`);
        fsExtra.ensureDirSync(path.dirname(customPermissionFile));
        fs.writeFileSync(customPermissionFile, this.generateXML("customPermission", sObject, automation), "utf-8");
        fsExtra.ensureDirSync(path.dirname(permissionSetFile));
        fs.writeFileSync(permissionSetFile, this.generateXML("permissionSet", sObject, automation), "utf-8");
        uxLog("log", this, c.grey(`Created: ${path.basename(customPermissionFile)} for ${sObject}`));
        uxLog("log", this, c.grey(`Created: ${path.basename(permissionSetFile)} for ${sObject}`));
    }
    generateFiles(targetSObjects, targetAutomations) {
        Object.keys(targetSObjects).forEach((developerName) => {
            targetAutomations.forEach((automation) => {
                this.generateXMLFiles(developerName, automation);
            });
        });
    }
    // Metadata handling
    async retrieveMetadataFiles(records, metadataType) {
        const recordsChunks = this.chunkArray(records);
        const results = [];
        for (const chunk of recordsChunks) {
            let command = `sf project retrieve start --metadata`;
            command += chunk
                .map((record) => {
                return metadataType === "ValidationRule"
                    ? ` ValidationRule:${record.EntityDefinition.QualifiedApiName}.${record.ValidationName}`
                    : ` ApexTrigger:${record.Name}`;
            })
                .join(" ");
            try {
                const result = await execCommand(`${command} --ignore-conflicts --json`, this, {
                    debug: false,
                    retry: {
                        retryDelay: 30,
                        retryStringConstraint: "error",
                        retryMaxAttempts: 3,
                    },
                });
                results.push(result);
            }
            catch (error) {
                uxLog("error", this, c.red(`Error retrieving ${metadataType}: ${error}`));
            }
        }
        return results;
    }
    chunkArray(array, chunkSize = 25) {
        return Array.from({ length: Math.ceil(array.length / chunkSize) }, (_, i) => array.slice(i * chunkSize, (i + 1) * chunkSize));
    }
    // Validation Rules
    async handleValidationRuleFile(filePath, sObject, name) {
        try {
            const fileContent = await parseXmlFile(filePath);
            if (!fileContent?.ValidationRule?.errorConditionFormula?.[0] ||
                typeof fileContent.ValidationRule.errorConditionFormula[0] !== "string") {
                return {
                    sObject,
                    name,
                    action: STATUS.FAILED,
                    comment: "Invalid validation rule format or missing error condition formula",
                };
            }
            const validationRuleContent = fileContent.ValidationRule.errorConditionFormula[0];
            const bypassPermissionName = `$Permission.Bypass${sObject}VRs`;
            if (typeof validationRuleContent === "string" &&
                validationRuleContent.includes(bypassPermissionName)) {
                return {
                    sObject,
                    name,
                    action: STATUS.IGNORED,
                    comment: "SFDX-Hardis Bypass already implemented",
                };
            }
            if (typeof validationRuleContent === "string" &&
                /bypass/i.test(validationRuleContent)) {
                return {
                    sObject,
                    name,
                    action: STATUS.SKIPPED,
                    comment: "Another bypass mechanism exists",
                };
            }
            const creditsText = this.skipCredits
                ? ""
                : `/* Updated ${CREDITS_TEXT} */
      `;
            fileContent.ValidationRule.errorConditionFormula[0] = `${creditsText}
      AND( AND(NOT(${bypassPermissionName}), NOT($Permission.BypassAllVRs)), ${validationRuleContent})`;
            await writeXmlFile(filePath, fileContent);
            return {
                sObject,
                name,
                action: STATUS.ADDED,
                comment: "SFDX-Hardis Bypass implemented",
            };
        }
        catch (error) {
            return {
                sObject,
                name,
                action: STATUS.FAILED,
                comment: `Error processing file : ${error}`,
            };
        }
    }
    async applyBypassToValidationRules(connection, sObjects) {
        const validationRuleRecords = await this.queryValidationRules(connection, sObjects);
        if (!validationRuleRecords || validationRuleRecords.records.length === 0) {
            uxLog("log", this, c.grey("No validation rules found for the specified sObjects."));
            return;
        }
        uxLog("log", this, c.grey(`Processing ${validationRuleRecords.records.length} Validation Rules.`));
        const validationRulesTableReport = [];
        const eligibleMetadataFilePaths = [];
        if (this.retrieveFromOrg) {
            const retrievedValidationRulesChunks = await this.retrieveMetadataFiles(validationRuleRecords.records, "ValidationRule");
            for (const retrievedValidationRules of retrievedValidationRulesChunks) {
                if (retrievedValidationRules?.status !== 1 &&
                    retrievedValidationRules?.result?.files &&
                    Array.isArray(retrievedValidationRules.result.files) &&
                    retrievedValidationRules.result.files.length > 0) {
                    for (const metadataFile of retrievedValidationRules.result.files) {
                        if (metadataFile?.type !== "ValidationRule" ||
                            metadataFile?.problemType === "Error") {
                            continue;
                        }
                        const [sObject, name] = metadataFile.fullName.split(".");
                        const filePath = metadataFile.filePath;
                        eligibleMetadataFilePaths.push({ filePath, sObject, name });
                    }
                }
                else {
                    uxLog("log", this, c.grey("No Validation Rule files found in the retrieved metadata chunk."));
                }
            }
        }
        else {
            if (validationRuleRecords?.records) {
                for (const record of validationRuleRecords.records) {
                    const sObject = record.EntityDefinition.QualifiedApiName;
                    const name = record.ValidationName;
                    const filePath = await MetadataUtils.findMetaFileFromTypeAndName("ValidationRule", name);
                    if (filePath === null) {
                        // TODO: add to report instead of log
                        uxLog("log", this, c.grey(`The validation rule ${name} for sObject ${sObject} does not have a corresponding metadata file locally. Skipping.`));
                    }
                    else {
                        eligibleMetadataFilePaths.push({ filePath, sObject, name });
                    }
                }
            }
        }
        for (const eligibleMetadataFilePath of eligibleMetadataFilePaths) {
            validationRulesTableReport.push(await this.handleValidationRuleFile(eligibleMetadataFilePath.filePath, eligibleMetadataFilePath.sObject, eligibleMetadataFilePath.name));
        }
        uxLog("action", this, c.cyan(`Validation Rules bypass report:`));
        uxLogTable(this, validationRulesTableReport);
    }
    // Triggers
    async handleTriggerFile(filePath, name) {
        try {
            if (!fs.existsSync(filePath)) {
                return {
                    sObject: null,
                    name,
                    action: STATUS.FAILED,
                    comment: "File not found",
                };
            }
            const fileContent = fs.readFileSync(filePath, "utf-8");
            if (typeof fileContent !== "string") {
                return {
                    sObject: null,
                    name,
                    action: STATUS.FAILED,
                    comment: "Invalid file content format",
                };
            }
            const match = fileContent.match(/trigger\s+\w+\s+on\s+(\w+)\s*\([^)]*\)\s*{\s*/i);
            if (!match) {
                return {
                    sObject: null,
                    name,
                    action: STATUS.FAILED,
                    comment: "Unable to detect sObject",
                };
            }
            const sObject = match[1].replace(/__c$/, "");
            const bypassCheckLine = `if(FeatureManagement.checkPermission('Bypass${sObject}Triggers') || FeatureManagement.checkPermission('BypassAllTriggers')) { return; }`;
            if (fileContent.includes(bypassCheckLine)) {
                return {
                    sObject,
                    name,
                    action: STATUS.IGNORED,
                    comment: "Bypass already implemented",
                };
            }
            if (/bypass|PAD\.can/i.test(fileContent)) {
                return {
                    sObject,
                    name,
                    action: STATUS.SKIPPED,
                    comment: "Another bypass exists",
                };
            }
            const fullBypassLine = `${bypassCheckLine}${this.skipCredits ? "" : "// Updated " + CREDITS_TEXT}`;
            const openBraceIndex = fileContent.indexOf("{");
            const beforeBrace = fileContent.substring(0, openBraceIndex + 1);
            const afterBrace = fileContent.substring(openBraceIndex + 1).trimStart();
            fsExtra.ensureDirSync(path.dirname(filePath));
            fs.writeFileSync(filePath, `${beforeBrace}\n\t${fullBypassLine}\n\t${afterBrace}`, "utf-8");
            return {
                sObject,
                name,
                action: STATUS.ADDED,
                comment: "Bypass implemented",
            };
        }
        catch (error) {
            return {
                sObject: null,
                name,
                action: STATUS.FAILED,
                comment: `Error processing file : ${error}`,
            };
        }
    }
    async applyBypassToTriggers(connection, sObjects) {
        const triggerResults = await this.queryTriggers(connection);
        const filteredTriggersResults = this.filterTriggerResults(triggerResults, sObjects);
        if (!filteredTriggersResults || filteredTriggersResults?.length === 0) {
            uxLog("log", this, c.grey("No triggers found for the specified sObjects."));
            return;
        }
        const triggerReport = [];
        const eligibleMetadataFilePaths = [];
        if (this.retrieveFromOrg) {
            const retrievedTriggersChunks = await this.retrieveMetadataFiles(filteredTriggersResults, "ApexTrigger");
            for (const retrievedTriggers of retrievedTriggersChunks) {
                if (retrievedTriggers?.status !== 1 &&
                    retrievedTriggers?.result?.files &&
                    Array.isArray(retrievedTriggers.result.files) &&
                    retrievedTriggers.result.files.length > 0) {
                    for (const metadataFile of retrievedTriggers.result.files) {
                        if (metadataFile?.type !== "ApexTrigger" ||
                            !metadataFile?.filePath?.endsWith(".trigger") ||
                            metadataFile?.problemType === "Error") {
                            continue;
                        }
                        const name = metadataFile.fullName;
                        const filePath = metadataFile.filePath;
                        eligibleMetadataFilePaths.push({ filePath, name });
                    }
                }
                else {
                    uxLog("log", this, c.grey("No Trigger files found in the retrieved metadata chunk."));
                }
            }
        }
        else {
            if (filteredTriggersResults) {
                for (const record of filteredTriggersResults) {
                    const name = record.Name;
                    const filePath = await MetadataUtils.findMetaFileFromTypeAndName("ApexTrigger", name);
                    if (filePath === null) {
                        // TODO: add to report instead of log
                        uxLog("log", this, c.grey(`The trigger ${name} does not have a corresponding metadata file locally. Skipping.`));
                    }
                    else {
                        eligibleMetadataFilePaths.push({ filePath, name });
                    }
                }
            }
        }
        for (const eligibleMetadataFilePath of eligibleMetadataFilePaths) {
            triggerReport.push(await this.handleTriggerFile(eligibleMetadataFilePath.filePath, eligibleMetadataFilePath.name));
        }
        uxLog("action", this, c.cyan(`Trigger bypass report:`));
        uxLogTable(this, triggerReport);
    }
}
//# sourceMappingURL=bypass.js.map