global without sharing class Batch_MappingQRCodeToAsset implements Database.Batchable<sObject> {
    private String objectApiName  = null;
    private String whereStr = null;
    public Batch_MappingQRCodeToAsset(){}
    public Batch_MappingQRCodeToAsset(String objectApiName, String whereStr) {
        this.objectApiName = objectApiName;
        this.whereStr = whereStr;
    }
    global Database.QueryLocator start(Database.BatchableContext BC) {
        String query = '';
        switch on this.objectApiName {
            when null, '' {
                System.debug('No availabe object api name in start phase>>>>>>');
            }
            when 'Asset' {
                query ='select id,QRId__c FROM Asset ';
            }
            when 'Rental_Apply__c' {
                query ='select id,QRId__c FROM Rental_Apply__c ';
            }
            when 'Consum_Apply__c' {
                query ='select id,QRId__c FROM Consum_Apply__c ';
            }
            when 'TransferApply__c' {
                query ='select id,QRId__c FROM TransferApply__c ';
            }
            when 'ReceivingNote__c' {
                query ='select id,QRId__c FROM ReceivingNote__c ';
            }
            when else {
                System.debug('open soon>>>>>>>>>');
            }
        }
        if(String.isNotBlank(this.whereStr)) {
            query += this.whereStr;
        }
        System.debug('query>>>>>'+query);
        return Database.getQueryLocator(query);
    }

    global void execute(Database.BatchableContext BC, list<Sobject> scope) {
        if(scope.size() <= 0) {
            return;
        }
        switch on this.objectApiName {
            when 'Asset' {
                processAsset(scope);
            }
            when 'Rental_Apply__c' {
                processRentalApply(scope);
            }
            when 'Consum_Apply__c' {
                processConsumApply(scope);
            }
            when 'TransferApply__c' {
                processTransferApply(scope);
            }
            when 'ReceivingNote__c' {
                processReceivingNote(scope);
            }
            when else {
                System.debug('No availabe object api name in execution phase>>>>>>');
            }
        }
    }

    global void processReceivingNote(list<Sobject> scope) {
        Set<String> receivingNoteIdSet = new  Set<String>();
        List<ReceivingNote__c> updateReceivingNoteList = new List<ReceivingNote__c>();
        Set<String> receivingNoteVersionIdSet = new  Set<String>();
        for(Sobject targetObj : scope)  {
            ReceivingNote__c receivingNoteObj = (ReceivingNote__c)targetObj;
            receivingNoteIdSet.add(receivingNoteObj.Id);
        }
        String queryContentDocumentList = 'select id,ContentDocument.LatestPublishedVersionId,LinkedEntityId from ContentDocumentLink where LinkedEntityId IN :receivingNoteIdSet and LinkedEntity.type = \'ReceivingNote__c\' and ContentDocument.Title like \'QRCode-%\'';
        List<ContentDocumentLink> contentDocumentLinkList = Database.query(queryContentDocumentList);
        for(ContentDocumentLink contentDocumentLink : contentDocumentLinkList) {
            if (!receivingNoteVersionIdSet.contains(contentDocumentLink.LinkedEntityId)) {
                ReceivingNote__c tempReceivingNote = new ReceivingNote__c();
                tempReceivingNote.Id = contentDocumentLink.LinkedEntityId;
                tempReceivingNote.QRId__c = contentDocumentLink.ContentDocument.LatestPublishedVersionId;
                updateReceivingNoteList.add(tempReceivingNote);
                receivingNoteVersionIdSet.add(contentDocumentLink.LinkedEntityId);
            }
        }

        if(updateReceivingNoteList.size() > 0) {
            List<Database.SaveResult> saveResultsContents = Database.update(updateReceivingNoteList, false);
            insertLog(saveResultsContents,receivingNoteIdSet);
        }
    }

    global void processTransferApply(list<Sobject> scope) {
        Set<String> transferApplyIdSet = new  Set<String>();
        List<TransferApply__c> updateTransferApplyList = new List<TransferApply__c>();
        Set<String> transferApplyVersionIdSet = new  Set<String>();
        for(Sobject targetObj : scope)  {
            TransferApply__c transferApplyObj = (TransferApply__c)targetObj;
            transferApplyIdSet.add(transferApplyObj.Id);
        }
        String queryContentDocumentList = 'select id,ContentDocument.LatestPublishedVersionId,LinkedEntityId from ContentDocumentLink where LinkedEntityId IN :transferApplyIdSet and LinkedEntity.type = \'TransferApply__c\' and ContentDocument.Title like \'QRCode-%\'';
        List<ContentDocumentLink> contentDocumentLinkList = Database.query(queryContentDocumentList);
        for(ContentDocumentLink contentDocumentLink : contentDocumentLinkList) {
            if (!transferApplyVersionIdSet.contains(contentDocumentLink.LinkedEntityId)) {
                TransferApply__c tempTransferApply = new TransferApply__c();
                tempTransferApply.Id = contentDocumentLink.LinkedEntityId;
                tempTransferApply.QRId__c = contentDocumentLink.ContentDocument.LatestPublishedVersionId;
                updateTransferApplyList.add(tempTransferApply);
                transferApplyVersionIdSet.add(contentDocumentLink.LinkedEntityId);
            }
        }

        if(updateTransferApplyList.size() > 0) {
            List<Database.SaveResult> saveResultsContents = Database.update(updateTransferApplyList, false);
            insertLog(saveResultsContents,transferApplyIdSet);
        }
    }

    global void processConsumApply(list<Sobject> scope) {
        Set<String> consumApplyIdSet = new  Set<String>();
        List<Consum_Apply__c> updateConsumApplyList = new List<Consum_Apply__c>();
        Set<String> consumApplyVersionIdSet = new  Set<String>();
        for(Sobject targetObj : scope)  {
            Consum_Apply__c consumApplyIdObj = (Consum_Apply__c)targetObj;
            consumApplyIdSet.add(consumApplyIdObj.Id);
        }
        String queryContentDocumentList = 'select id,ContentDocument.LatestPublishedVersionId,LinkedEntityId from ContentDocumentLink where LinkedEntityId IN :consumApplyIdSet and LinkedEntity.type = \'Consum_Apply__c\' and ContentDocument.Title like \'QRCode-%\'';
        List<ContentDocumentLink> contentDocumentLinkList = Database.query(queryContentDocumentList);
        for(ContentDocumentLink contentDocumentLink : contentDocumentLinkList) {
            if (!consumApplyVersionIdSet.contains(contentDocumentLink.LinkedEntityId)) {
                Consum_Apply__c tempConsumApply = new Consum_Apply__c();
                tempConsumApply.Id = contentDocumentLink.LinkedEntityId;
                tempConsumApply.QRId__c = contentDocumentLink.ContentDocument.LatestPublishedVersionId;
                updateConsumApplyList.add(tempConsumApply);
                consumApplyVersionIdSet.add(contentDocumentLink.LinkedEntityId);
            }
        }

        if(updateConsumApplyList.size() > 0) {
            List<Database.SaveResult> saveResultsContents = Database.update(updateConsumApplyList, false);
            insertLog(saveResultsContents,consumApplyIdSet);
        }
    }

    global void processRentalApply(list<Sobject> scope) {
        Set<String> rentalApplyIdSet = new  Set<String>();
        List<Rental_Apply__c> updateRentalApplyList = new List<Rental_Apply__c>();
        Set<String> rentalApplyVersionIdSet = new  Set<String>();
        for(Sobject targetObj : scope)  {
            Rental_Apply__c rentalApplyObj = (Rental_Apply__c)targetObj;
            rentalApplyIdSet.add(rentalApplyObj.Id);
        }
        String queryContentDocumentList = 'select id,ContentDocument.LatestPublishedVersionId,LinkedEntityId from ContentDocumentLink where LinkedEntityId IN :rentalApplyIdSet and LinkedEntity.type = \'Rental_Apply__c\' and ContentDocument.Title like \'QRCode-%\'';
        List<ContentDocumentLink> contentDocumentLinkList = Database.query(queryContentDocumentList);
        for(ContentDocumentLink contentDocumentLink : contentDocumentLinkList) {
            if (!rentalApplyVersionIdSet.contains(contentDocumentLink.LinkedEntityId)) {
                Rental_Apply__c tempRentalApply = new Rental_Apply__c();
                tempRentalApply.Id = contentDocumentLink.LinkedEntityId;
                tempRentalApply.QRId__c = contentDocumentLink.ContentDocument.LatestPublishedVersionId;
                updateRentalApplyList.add(tempRentalApply);
                rentalApplyVersionIdSet.add(contentDocumentLink.LinkedEntityId);
            }
           
        }

        if(updateRentalApplyList.size() > 0) {
            List<Database.SaveResult> saveResultsContents = Database.update(updateRentalApplyList, false);
            insertLog(saveResultsContents,rentalApplyIdSet);
        }
    }

    global void processAsset(list<Sobject> scope) {
        Set<String> assetIdSet = new  Set<String>();
        List<Asset> updateAssetSet = new List<Asset>();
        Set<String> assetWithVersionIdSet = new  Set<String>();
        for(Sobject targetObj : scope)  {
            Asset assetObj = (Asset)targetObj;
            assetIdSet.add(assetObj.Id);
        }
        String queryContentDocumentList = 'select id,ContentDocument.LatestPublishedVersionId,LinkedEntityId from ContentDocumentLink where LinkedEntityId IN :assetIdSet and LinkedEntity.type = \'Asset\' and ContentDocument.Title = \'QRCode\'';
        List<ContentDocumentLink> contentDocumentLinkList = Database.query(queryContentDocumentList);
        for(ContentDocumentLink contentDocumentLink : contentDocumentLinkList) {
            if (!assetWithVersionIdSet.contains(contentDocumentLink.LinkedEntityId)) {
                Asset tempAsset = new Asset();
                tempAsset.Id = contentDocumentLink.LinkedEntityId;
                tempAsset.QRId__c = contentDocumentLink.ContentDocument.LatestPublishedVersionId;
                updateAssetSet.add(tempAsset);
                assetWithVersionIdSet.add(contentDocumentLink.LinkedEntityId);
            }
        }

        if(updateAssetSet.size() > 0) {
            List<Database.SaveResult> saveResultsContents = Database.update(updateAssetSet, false);
            insertLog(saveResultsContents,assetIdSet);
        }
    }

    global void insertLog(List<Database.SaveResult> saveResults,Set<String> mainIds) {
        Transaction_Log__c traLog = new Transaction_Log__c();
        List<Map<String,String>> logMapList = new List<Map<String,String>>();
        for (Database.SaveResult result : saveResults) {
            String recordId = result.getId();
            if (!result.isSuccess()) {
                for (Database.Error error : result.getErrors()) {
                    Map<String,String> logMap = new Map<String,String>();
                    String errorMsg = error.getMessage();
                    logMap.put('recordId',recordId);
                    logMap.put('errorMsg',errorMsg);
                    logMapList.add(logMap);
                }
            }
        }
        if(logMapList.size() > 0){
            Map<String,String> mainIdMap = new Map<String,String>();
            mainIdMap.put(this.objectApiName + 'Ids',JSON.serialize(mainIds));
            logMapList.add(mainIdMap);
            traLog.Response__c = JSON.serialize(logMapList);
            traLog.Module__c = 'QR mapping Convert Transaction';
            Insert traLog;
        }
    }
    
    global void finish(Database.BatchableContext BC) {

    }


}