/* jscpd:ignore-start */
import { SfCommand, Flags, requiredOrgFlagWithDeprecations } from '@salesforce/sf-plugins-core';
import { Messages } from '@salesforce/core';
import c from 'chalk';
import { uxLog, uxLogTable } from '../../../../common/utils/index.js';
import { soqlQueryTooling } from '../../../../common/utils/apiUtils.js';
import { NotifProvider } from '../../../../common/notifProvider/index.js';
import { generateCsvFile, generateReportPath } from '../../../../common/utils/filesUtils.js';
import { getNotificationButtons, getOrgMarkdown, getSeverityIcon } from '../../../../common/utils/notifUtils.js';
import moment from 'moment';
import { CONSTANTS } from '../../../../config/index.js';
import { setConnectionVariables } from '../../../../common/utils/orgUtils.js';
Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
const messages = Messages.loadMessages('sfdx-hardis', 'org');
export default class DiagnoseReleaseUpdates extends SfCommand {
    static title = 'Check Release Updates of an org';
    static description = `Export Release Updates into a CSV file with selected criteria, and highlight Release Updates that should be checked.

Before publishing **Breaking Changes** ❌, Salesforce announce them in the setup menu [**Release Updates**](https://help.salesforce.com/s/articleView?id=sf.release_updates.htm&type=5)

⚠️ Some of them are very important, because if you don't make the related upgrades in time (ex: before Winter 25) , your production org can crash !

This command is part of [sfdx-hardis Monitoring](${CONSTANTS.DOC_URL_ROOT}/salesforce-monitoring-release-updates/) and can output Grafana, Slack and MsTeams Notifications.
`;
    static examples = [
        '$ sf hardis:org:diagnose:releaseupdates',
    ];
    static flags = {
        outputfile: Flags.string({
            char: 'f',
            description: 'Force the path and name of output report file. Must end with .csv',
        }),
        debug: Flags.boolean({
            char: 'd',
            default: false,
            description: messages.getMessage('debugMode'),
        }),
        websocket: Flags.string({
            description: messages.getMessage('websocket'),
        }),
        skipauth: Flags.boolean({
            description: 'Skip authentication check when a default username is required',
        }),
        'target-org': requiredOrgFlagWithDeprecations,
    };
    static requiresProject = false;
    debugMode = false;
    releaseUpdatesRecords = [];
    outputFile;
    outputFilesRes = {};
    /* jscpd:ignore-end */
    async run() {
        const { flags } = await this.parse(DiagnoseReleaseUpdates);
        this.debugMode = flags.debug || false;
        this.outputFile = flags.outputfile || null;
        const conn = flags['target-org'].getConnection();
        uxLog("action", this, c.cyan(`Extracting Release Updates and checks to perform in ${conn.instanceUrl} ...`));
        // Fetch ReleaseUpdate records
        const releaseUpdatesQuery = `SELECT StepStage,Status,Category,Title,DueDate,Description,Release,ReleaseLabel,ReleaseDate,ApiVersion,DurableId,HasNewSteps,IsReleased,SupportsRevoke,DeveloperName ` +
            `FROM ReleaseUpdate ` +
            `WHERE StepStage IN ('Upcoming','OverDue') AND Status IN ('Invocable','Revocable','Nascent','Invoked','Info') AND DueDate >= LAST_N_DAYS:60 ` +
            `ORDER BY DueDate ASC`;
        const queryRes = await soqlQueryTooling(releaseUpdatesQuery, conn);
        const severityIconWarning = getSeverityIcon('warning');
        const severityIconError = getSeverityIcon('error');
        this.releaseUpdatesRecords = queryRes.records.map((record) => {
            delete record.attributes;
            record.severityIcon = record.StepStage === 'OverDue' ? severityIconError : severityIconWarning;
            return record;
        });
        // Process result
        if (this.releaseUpdatesRecords.length > 0) {
            // Generate output CSV file
            this.outputFile = await generateReportPath('release-updates', this.outputFile);
            this.outputFilesRes = await generateCsvFile(this.releaseUpdatesRecords, this.outputFile);
            // Build notification
            const orgMarkdown = await getOrgMarkdown(flags['target-org']?.getConnection()?.instanceUrl);
            const notifButtons = await getNotificationButtons();
            const notifSeverity = 'warning';
            const notifText = `${this.releaseUpdatesRecords.length} Release Updates to check have been found in ${orgMarkdown}`;
            let notifDetailText = '';
            for (const releaseUpdate of this.releaseUpdatesRecords) {
                notifDetailText += `• *${releaseUpdate.Title}* (${releaseUpdate.StepStage},${releaseUpdate.Status},${releaseUpdate.Category}), due for ${moment(releaseUpdate.DueDate).format("ll")}\n`;
            }
            const notifAttachments = [{ text: notifDetailText }];
            // Post notif
            await setConnectionVariables(flags['target-org']?.getConnection()); // Required for some notifications providers like Email
            await NotifProvider.postNotifications({
                type: 'RELEASE_UPDATES',
                text: notifText,
                attachments: notifAttachments,
                buttons: notifButtons,
                severity: notifSeverity,
                attachedFiles: this.outputFilesRes.xlsxFile ? [this.outputFilesRes.xlsxFile] : [],
                logElements: this.releaseUpdatesRecords,
                data: { metric: this.releaseUpdatesRecords.length },
                metrics: {
                    ReleaseUpdates: this.releaseUpdatesRecords.length,
                },
            });
            // Display output
            const releaseUpdatesLight = this.releaseUpdatesRecords.map(releaseUpdate => {
                return {
                    Title: releaseUpdate.Title,
                    StepStage: releaseUpdate.StepStage,
                    Status: releaseUpdate.Status,
                    Category: releaseUpdate.Category,
                    DueDate: moment(releaseUpdate.DueDate).format('ll')
                };
            });
            uxLog("action", this, c.cyan(notifText));
            uxLogTable(this, releaseUpdatesLight);
        }
        else {
            uxLog("success", this, c.green("No release updates has been found"));
        }
        // Return an object to be displayed with --json
        return {
            status: this.releaseUpdatesRecords.length > 0 ? 1 : 0,
            suspectRecords: this.releaseUpdatesRecords,
            csvLogFile: this.outputFile,
        };
    }
}
//# sourceMappingURL=releaseupdates.js.map