/**********************************************************************************************************
 * Name         : TempFormResponseCountAlertBatch
 * Purpose      : Job to alert in case the TFR count reaches the threshold
 **********************************************************************************************************/

public with sharing class TempFormResponseCountAlertBatch implements Database.Batchable<sObject>, Database.Stateful, Schedulable, Database.RaisesPlatformEvents {
    @TestVisible
    private Integer totalCount = 0;
    private final Integer TFR_COUNT_ALERT_THRESHOLD = ConfigUtils.getConfigInt(ConfigUtils.TFR_COUNT_ALERT_THRESHOLD);
    @TestVisible
    private List<AggregateResult> tfrCountByGroup = new List<AggregateResult>();

    public Iterable<sObject> start(Database.BatchableContext bc) {
        tfrCountByGroup = [
            SELECT
                Form_ID__r.TLA_ID__r.Territory_ID__r.Territory__c territory,
                Form_ID__r.TLA_ID__r.Label_ID__r.Name label,
                Promo_ID__r.Promo_Description__c promotion,
                count(Id) amount
            FROM Temp_Form_Response__c
            WHERE
                Source__c != :UtilConstants.FILE_UPLOAD_TOOL
                AND Times_Processed__c < :ConfigUtils.getConfigInt(ConfigUtils.TFR_JOB_MAX_RETRY)
            GROUP BY
                Form_ID__r.TLA_ID__r.Territory_ID__r.Territory__c,
                Form_ID__r.TLA_ID__r.Label_ID__r.Name,
                Promo_ID__r.Promo_Description__c
            ORDER BY count(Id) DESC
        ];

        return new List<Temp_Form_Response__c>();
    }

    public void execute(Database.BatchableContext bc, List<Temp_Form_Response__c> tempFormResponses) {
    }

    public void finish(Database.BatchableContext bc) {
        for (AggregateResult ar : tfrCountByGroup) {
            totalCount += Integer.valueOf(ar.get('amount'));
        }

        if (totalCount >= TFR_COUNT_ALERT_THRESHOLD) {
            EmailTemplate emailTemplate = [
                SELECT HtmlValue, Subject
                FROM EmailTemplate
                WHERE DeveloperName = 'TfrCountAlertBatchJobEmailTemplate'
            ];
            String tdElements = '';

            for (AggregateResult ar : tfrCountByGroup) {
                String td =
                    '<tr>' +
                    +'<td>' +
                    ar.get('territory') +
                    '</td>' +
                    +'<td>' +
                    ar.get('label') +
                    '</td>' +
                    +'<td>' +
                    ar.get('promotion') +
                    '</td>' +
                    +'<td>' +
                    Integer.valueOf(ar.get('amount')).format() +
                    '</td>' +
                    '</tr>';

                tdElements += td;
            }

            String emailContent = emailTemplate.HtmlValue;

            emailContent = emailContent.replace('{{TFR_ROWS}}', tdElements);
            emailContent = emailContent.replace('{{TFR_COUNT_THRESHOLD}}', TFR_COUNT_ALERT_THRESHOLD.format());
            emailContent = emailContent.replace('{{TFR_COUNT}}', totalCount.format());

            Messaging.SingleEmailMessage message = new Messaging.SingleEmailMessage();
            message.setToAddresses(ConfigUtils.getConfigMultipleStrings(ConfigUtils.TFR_COUNT_ALERT_EMAIL_RECIPIENTS));
            message.setSubject(emailTemplate.Subject);
            message.setSenderDisplayName(ConfigUtils.getConfigString(ConfigUtils.TFR_COUNT_ALERT_EMAIL_SENDER));
            message.setHtmlBody(emailContent);
            Messaging.sendEmail(new List<Messaging.SingleEmailMessage>{ message });
        }
    }

    public void execute(SchedulableContext sc) {
        Database.executeBatch(new TempFormResponseCountAlertBatch());
    }

    public static void schedule() {
        BatchJobUtils.scheduleJob(
            new TempFormResponseCountAlertBatch(),
            ConfigUtils.getConfigString(ConfigUtils.TFR_COUNT_ALERT_CRON_EXPS)
        );
    }
}