/***********************************************************************************************************
 * Name         : WelcomeEmailBatch
 * Purpose      : Batch to make callouts to MC in order to send welcome emails to the fans.
 **********************************************************************************************************/
public with sharing class WelcomeEmailBatch implements Database.Batchable<SObject>, Database.AllowsCallouts, Database.Stateful, Database.RaisesPlatformEvents {
    Integer index = 0;
    Integer daysToProcess;
    Boolean isAnotherJobInstanceRunning = false;
    Boolean isSubFanObj = true;
    Map<String, List<SObject>> mapErrorObjectsList = new Map<String, List<SObject>>();

    public WelcomeEmailBatch() {
        this.isSubFanObj = true;
        this.daysToProcess = 1;
    }
    public WelcomeEmailBatch(Boolean isSubFanObj, Integer daysToProcess) {
        this.isSubFanObj = isSubFanObj;
        this.daysToProcess = daysToProcess;
    }

    public Database.queryLocator start(Database.BatchableContext BC) {
        String query;
        isAnotherJobInstanceRunning = TempFormResponseBatchUtils.isAnotherJobInstanceRunning(
            BC.getJobId(),
            'WelcomeEmailBatch'
        );
        if (isAnotherJobInstanceRunning) {
            query = 'SELECT Id FROM SubscriptionFanTriggerSendMapping__c LIMIT 0';
        } else {
            if (isSubFanObj) {
                query =
                    'SELECT Fan_ID__r.Encrypted_ID__c, Fan_ID__r.Email__c, Fan_ID__r.First_Name__c, Fan_ID__c, Fan_Id__r.Postal_code__c, ' +
                    'Form_id__c, Form_id__r.TLA_ID__c, Fan_ID__r.Last_Name__c, Triggered_Send_Definition_Key__c, MC_MID__c, ' +
                    'Subscription_ID__r.Mailing_List_ID__c, Subscription_ID__r.Mailing_List_ID__r.Tla_ID__r.Territory_ID__c, ' +
                    'Subscription_ID__r.Mailing_List_ID__r.Tla_ID__r.Label_ID__r.Name,' +
                    'Subscription_ID__r.Mailing_List_ID__r.Tla_ID__r.Artist_ID__r.Artist__c, Subscription_ID__r.Promo_Id__r.Name, ' +
                    'Form_ID__r.Tla_ID__r.Territory_ID__c, Form_ID__r.Tla_ID__r.Label_Id__r.Name ,' +
                    'Form_ID__r.Tla_ID__r.Artist_ID__r.Artist__c, Welcome_Email_Delivered__c FROM SubscriptionFanTriggerSendMapping__c ' +
                    'WHERE Welcome_Email_Delivered__c = FALSE AND Welcome_Email_Triggered__c = FALSE AND LastModifiedDate >= LAST_N_DAYS: ' +
                    daysToProcess +
                    ' ORDER BY LastModifiedDate ASC';
            } else {
                query =
                    'SELECT Id, Form_ID__c, Parent_MID__c,triggered_send_definition_key__c, Email__c, Welcome_Email_Delivered__c ' +
                    'FROM DO_Temp_Form_Response__c WHERE Welcome_Email_Delivered__c = FALSE AND MC_Error_Message__c = NULL ' +
                    'AND LastModifiedDate >= LAST_N_DAYS: ' +
                    daysToProcess +
                    ' ORDER BY LastModifiedDate ASC';
            }
        }

        return Database.getQueryLocator(query);
    }

    public void execute(Database.BatchableContext BC, List<SObject> scope) {
        Map<String, List<SObject>> midTsdkMap = WelcomeEmailBatchHelper.groupByTSDKandMID(scope);
        List<SObject> sObjectsToUpdate = WelcomeEmailBatchHelper.createTriggeredSend(midTsdkMap);
        TriggerControl.disableTrigger(DoTempFormResponseTriggerHandler.SELF, TriggerOperation.BEFORE_UPDATE);
        update sObjectsToUpdate;
        WelcomeEmailBatchHelper.mapErrors(mapErrorObjectsList, sObjectsToUpdate, isSubFanObj);
        TriggerControl.enableTrigger(DoTempFormResponseTriggerHandler.SELF, TriggerOperation.BEFORE_UPDATE);
    }

    public void finish(Database.BatchableContext BC) {
        System.OrgLimit singleEmailLimit = OrgLimits.getMap().get('SingleEmail');

        if (
            !mapErrorObjectsList.isEmpty() &&
            singleEmailLimit.getValue() < singleEmailLimit.getLimit() - mapErrorObjectsList.keySet().size()
        ) {
            WelcomeEmailBatchHelper.sendErrorEmailNotification(mapErrorObjectsList, isSubFanObj);
        }

        Boolean shouldKeepRunning = ConfigUtils.getConfigBoolean(ConfigUtils.WE_JOB_KEEP_RUNNING);
        if (!Test.isRunningTest() && !isAnotherJobInstanceRunning && shouldKeepRunning) {
            isSubFanObj = !isSubFanObj;
            Database.executeBatch(new WelcomeEmailBatch(isSubFanObj, daysToProcess), 50);
        }
    }
}