/***********************************************************************************************************
 * Name         : TempFormResponseFileUploadBatch
 * Purpose      : Job to process TempFormResponse records created by File Uploads
 **********************************************************************************************************/

public without sharing class TempFormResponseFileUploadBatch implements Database.Batchable<SObject>, Database.Stateful, Database.RaisesPlatformEvents {
    @TestVisible
    private String query;
    private Id fileUploadId;
    public Set<Id> activeJobsIds;

    @TestVisible
    Integer totalRecords = 0;
    Integer recordsProcessed = 0;
    Set<Id> reprocessedFileUploads = new Set<Id>();

    public TempFormResponseFileUploadBatch(Id fileUploadId) {
        this.fileUploadId = fileUploadId;
        query = TempFormResponseBatchUtils.fileUploadQuery;
    }

    public TempFormResponseFileUploadBatch() {
        this.activeJobsIds = TempFormResponseBatchUtils.getActiveTfrFileUploadJobIds();
        query = TempFormResponseBatchUtils.fileUploadReprocessQuery;
    }

    public Database.queryLocator start(Database.BatchableContext bc) {
        if (!String.isBlank(fileUploadId)) {
            totalRecords = Database.countQuery(TempFormResponseBatchUtils.fileUploadCountQuery);
        }
        return Database.getQueryLocator(query);
    }

    public void execute(Database.BatchableContext bc, List<Temp_Form_Response__c> tempFormResponses) {
        List<Form_Response__c> formResponsesToInsert = new List<Form_Response__c>();
        List<Temp_Form_Response__c> tfrsToDelete = new List<Temp_Form_Response__c>();

        List<Temp_Form_Response__c> tfrsWithoutFan = new List<Temp_Form_Response__c>();
        for (Temp_Form_Response__c tfr : tempFormResponses) {
            if (String.isBlank(tfr.Fan_ID__c)) {
                tfrsWithoutFan.add(tfr);
            }
        }

        if (!tfrsWithoutFan.isEmpty()) {
            TempFormResponseTriggerHelper.upsertFans(tfrsWithoutFan);
        }

        for (Temp_Form_Response__c tfr : tempFormResponses) {
            if (!String.isBlank(tfr.Fan_ID__c)) {
                reprocessedFileUploads.add(tfr.Sub_Upload_Source__c);
                formResponsesToInsert.add(TempFormResponseBatchUtils.mapTempFormResponseToFormResponse(tfr));
                tfrsToDelete.add(tfr);
            }
        }

        insert formResponsesToInsert;
        Database.delete(tfrsToDelete, false);

        if (!String.isBlank(fileUploadId)) {
            recordsProcessed += tfrsToDelete.size();
            Sub_Upload_Util__c subUpload = new Sub_Upload_Util__c(
                Id = fileUploadId,
                Progress__c = 50 + ((recordsProcessed * 100 / totalRecords) / 2)
            );
            if (subUpload.Progress__c == 100) {
                subUpload.Status__c = SubUploadBatchUtils.SUB_UPLOAD_COMPLETED_STATUS;
            }
            Database.update(subUpload, false);
        }
    }

    public void finish(Database.BatchableContext bc) {
        if ((String.isBlank(fileUploadId) || recordsProcessed != totalRecords) && !reprocessedFileUploads.isEmpty()) {
            List<AggregateResult> aggResults = [
                SELECT COUNT(Id), Sub_Upload_Source__c
                FROM Temp_Form_Response__c
                WHERE Sub_Upload_Source__c IN :reprocessedFileUploads
                GROUP BY Sub_Upload_Source__c
            ];

            for (AggregateResult agg : aggResults) {
                reprocessedFileUploads.remove(String.valueOf(agg.get('Sub_Upload_Source__c')));
            }

            if (!reprocessedFileUploads.isEmpty()) {
                List<Sub_Upload_Util__c> subUploadsToUpdate = new List<Sub_Upload_Util__c>();
                for (Id subUploadId : reprocessedFileUploads) {
                    subUploadsToUpdate.add(
                        new Sub_Upload_Util__c(
                            Id = subUploadId,
                            Progress__c = 100,
                            Status__c = SubUploadBatchUtils.SUB_UPLOAD_COMPLETED_STATUS
                        )
                    );
                }
                Database.update(subUploadsToUpdate, false);
            }
        }
    }
}
