/***********************************************************************************************************
 * Name         : FanMCAllContactsVerificationBatch
 * Purpose      : Batch job to verify if the FanMcs were deleted from MC
 **********************************************************************************************************/
public with sharing class FanMCAllContactsVerificationBatch implements Database.Batchable<sObject>, Database.Allowscallouts, Database.Stateful, Schedulable, Database.RaisesPlatformEvents {
    private Integer lastModifiedDay;
    public List<Fan_MC_Cleanup__c> fanMCsNotDeletedEmail = new List<Fan_MC_Cleanup__c>();

    public MarketingCloudHelper.MarketingCloudAuthResponseWrapper authResponseWrapper;

    public FanMCAllContactsVerificationBatch() {
        this.lastModifiedDay = 7;
    }

    public FanMCAllContactsVerificationBatch(Integer lastModifiedDay) {
        this.lastModifiedDay = lastModifiedDay;
    }

    public Database.QueryLocator start(Database.BatchableContext BC) {
        String errorMessage = FanMCAllContactsVerificationHelper.OP_ID_NOT_FOUND_MESSAGE;
        String query =
            'SELECT Id, Fan_Id__c, Is_Deleted_From_MC_All_Subscribers__c, Status__c, MC_Error_Message__c, Operation_ID__c, TimesChecked__c, CreatedDate FROM Fan_MC_Cleanup__c ' +
            'WHERE Is_Deleted_From_MC_All_Subscribers__c = FALSE AND Operation_ID__c != NULL AND ' +
            'MC_Error_Message__c != :errorMessage AND ' +
            'Delete_Request_Triggered__c = TRUE AND (LastModifiedDate < LAST_N_DAYS: ' +
            lastModifiedDay +
            ' OR TimesChecked__c > 0) ORDER BY Operation_ID__c';
        return Database.getQueryLocator(query);
    }

    public void execute(Database.BatchableContext BC, List<Fan_MC_Cleanup__c> fanMCs) {
        List<Fan_MC_Cleanup__c> fanMCsNotDeleted = new List<Fan_MC_Cleanup__c>();
        authResponseWrapper = MarketingCloudHelper.getTokenForContactsDelete(authResponseWrapper);

        List<Fan_MC_Cleanup__c> fanMCsToDelete = new List<Fan_MC_Cleanup__c>();
        Map<String, List<Fan_MC_Cleanup__c>> opIdListFanMC = FanMCAllContactsVerificationHelper.groupByOperationId(
            fanMCs
        );
        for (String operationId : opIdListFanMC.keySet()) {
            FanMCAllContactsVerificationHelper.performVerificationCallout(
                operationId,
                opIdListFanMC.get(operationId),
                authResponseWrapper.authResponse.access_token
            );
        }
        for (Fan_MC_Cleanup__c fanMC : fanMCs) {
            if (fanMC.Is_Deleted_From_MC_All_Subscribers__c) {
                fanMCsToDelete.add(fanMC);
            } else {
                fanMCsNotDeleted.add(fanMC);
            }
        }

        fanMCsNotDeletedEmail.addAll(fanMCsNotDeleted);
        update fanMCsNotDeleted;
        delete fanMCsToDelete;
    }

    public void finish(Database.BatchableContext BC) {
        BatchJobUtils.sendEmail(
            ConfigUtils.MC_VERIFICATION_BATCH_RECIPIENTS,
            ConfigUtils.MC_VERIFICATION_BATCH_SENDER,
            ConfigUtils.MC_VERIFICATION_BATCH_SUBJECT,
            ConfigUtils.MC_VERIFICATION_BATCH_EMAIL_BODIES,
            'notDeletedRecords.csv',
            fanMCsNotDeletedEmail
        );
    }

    public void execute(SchedulableContext sc) {
        Database.executeBatch(new FanMCAllContactsVerificationBatch(), 2000);
    }

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