/*
 * Author: Bubba Li
 * Created Date: 04/22/2022
 * Purpose: sync agency contact to aws
 * Test Class: SyncAccountContactToAWS_Test
 * History: 
 * 		04/22/2022 - Bubba Li - Initial Code.
 * 
 * */
global class  SyncAccountContactToAWS implements Schedulable,Database.Batchable<SObject>,Database.AllowsCallouts{

    global String query;
    global String scheduleId{set;get;}
    global Map<Id,Contact> ContactMap{set;get;}
    global SyncAccountContactToAWS(String query) {
        this.query = query;
    }
    global SyncAccountContactToAWS(String query,Map<Id,Contact> ContactMap) {
        this.query = query;
        this.ContactMap = ContactMap;
    }
    global SyncAccountContactToAWS() {
        this.query = 'SELECT id,Doctor_Division1__c,Doctor_Division1_Encrypted__c,Name,Name_Encrypted__c,Type__c,Type_Encrypted__c,AWS_Data_Id__c,Contact__c, Contact__r.Doctor_Division1_Encrypted__c,Contact__r.LastName_Encrypted__c, Contact__r.Type_Encrypted__c FROM Agency_Contact__c WHERE AWS_Data_Id__c =\'\' And Contact__c != null order by lastmodifieddate desc';
    }
    global SyncAccountContactToAWS(String query,String scId) {
        if(String.isBlank(query)||String.isEmpty(query)){
            this.query = 'SELECT id,Doctor_Division1__c,Doctor_Division1_Encrypted__c,Name,Name_Encrypted__c,Type__c,Type_Encrypted__c,AWS_Data_Id__c,Contact__c, Contact__r.Doctor_Division1_Encrypted__c,Contact__r.LastName_Encrypted__c, Contact__r.Type_Encrypted__c FROM Agency_Contact__c WHERE AWS_Data_Id__c =\'\' And Contact__c != null order by lastmodifieddate desc';
        }else{
            this.query = query;
        }
        system.debug('This query from Batch:'+this.query);
        this.scheduleId = scId;
    }
    //zhj 2022-01-03 start
    global SyncAccountContactToAWS(String query,String scId,Map<Id,Contact> ContactMap) {
        if(String.isBlank(query)||String.isEmpty(query)){
            this.query = 'SELECT id,Doctor_Division1__c,Doctor_Division1_Encrypted__c,Name,Name_Encrypted__c,Type__c,Type_Encrypted__c,AWS_Data_Id__c,Contact__c, Contact__r.Doctor_Division1_Encrypted__c,Contact__r.LastName_Encrypted__c, Contact__r.Type_Encrypted__c FROM Agency_Contact__c WHERE AWS_Data_Id__c =\'\' And Contact__c != null order by lastmodifieddate desc';
        }else{
            this.query = query;
        }
        system.debug('This query from Batch:'+this.query);
        this.scheduleId = scId;
        this.ContactMap = ContactMap;
    }
    //zhj 2022-01-03 end
    global Database.QueryLocator start(Database.BatchableContext bc) {
        system.debug('Query by custom soql:'+this.query);  
        return Database.getQueryLocator(this.query);
    }
    global void execute(Database.BatchableContext BC, list<Agency_Contact__c> scope) {
        System.debug('ContactMap = ' + ContactMap);
        if(scope!=null && scope.size()>0){
            //zhj MEBG新方案改造 2022-11-28 start
            for(Agency_Contact__c  aContact:scope){
                //aContact.Doctor_Division1_Encrypted__c = aContact.Contact__c!=null&&aContact.Contact__r.Doctor_Division1_Encrypted__c!=''?aContact.Contact__r.Doctor_Division1_Encrypted__c:'';
                //aContact.Name_Encrypted__c =  aContact.Contact__c!=null&&aContact.Contact__r.LastName_Encrypted__c!=''?aContact.Contact__r.LastName_Encrypted__c:'';
                //aContact.Type_Encrypted__c =  aContact.Contact__c!=null&&aContact.Contact__r.Type_Encrypted__c!=''?aContact.Contact__r.Type_Encrypted__c:'';
                aContact.AWS_Data_Id__c = '';
            }
            system.debug('Agency Contact Info to AWS:'+JSON.serialize(scope));

            Map<String,PIHelper.PIIntegration> staticResource = new Map<String,PIHelper.PIIntegration>();
            staticResource.put('Contact',PIHelper.getPIIntegrationInfo('Contact'));
            staticResource.put('Agency_Contact__c',PIHelper.getPIIntegrationInfo('Agency_Contact__c'));
            Map<String, Map<String, PI_Field_Policy_Detail__c>> mmsp = new Map<String, Map<String,PI_Field_Policy_Detail__c>>();
            for (String key : staticResource.keySet()) {
                mmsp.put(key, new Map<String,PI_Field_Policy_Detail__c>());
                for (PI_Field_Policy_Detail__c detail : staticResource.get(key).PIDetails) {
                    mmsp.get(key).put(detail.SF_Field_API_Name__c, detail);
                }
            }

            System.debug('mmsp = ' + mmsp);
            List<AWSServiceTool2V2.EncryptPushRequestBody> EncryptPushList = new List<AWSServiceTool2V2.EncryptPushRequestBody>();
            for(Agency_Contact__c ac : scope){
                AWSServiceTool2V2.EncryptPushRequestBody EncryptPush = new AWSServiceTool2V2.EncryptPushRequestBody();
                EncryptPush.dataId = ac.AWS_Data_Id__c != null ?ac.AWS_Data_Id__c:'';
                EncryptPush.sfRecordId = ac.Id;
                EncryptPush.fieldsMapping = new Map<String, List<AWSServiceTool2V2.EncryptPushRes>>();
                List<AWSServiceTool2V2.EncryptPushRes> resList = new List<AWSServiceTool2V2.EncryptPushRes>();
                AWSServiceTool2V2.EncryptPushRes res= new AWSServiceTool2V2.EncryptPushRes();
                res.isQueryDb = true;
                res.value = '';
                res.table = staticResource.get('Contact').awsTableName;
                //res.dataId = ContactMap.get(ac.Contact__c).AWS_Data_Id__c;
                res.dataId = (ContactMap == null || ContactMap.size() == 0) ?'':ContactMap.get(ac.Contact__c).AWS_Data_Id__c;
                res.field = mmsp.get('Contact').get('LastName').AWS_Field_API__c;
                resList.add(res);

                List<AWSServiceTool2V2.EncryptPushRes> resList2 = new List<AWSServiceTool2V2.EncryptPushRes>();
                AWSServiceTool2V2.EncryptPushRes res2= new AWSServiceTool2V2.EncryptPushRes();
                res2.isQueryDb = true;
                res2.value = '';
                res2.table = staticResource.get('Contact').awsTableName;
                //res2.dataId = ContactMap.get(ac.Contact__c).AWS_Data_Id__c;
                res2.dataId = (ContactMap == null || ContactMap.size() == 0) ?'':ContactMap.get(ac.Contact__c).AWS_Data_Id__c;
                res2.field = mmsp.get('Contact').get('Type__c').AWS_Field_API__c;
                resList2.add(res2);

                List<AWSServiceTool2V2.EncryptPushRes> resList3 = new List<AWSServiceTool2V2.EncryptPushRes>();
                AWSServiceTool2V2.EncryptPushRes res3= new AWSServiceTool2V2.EncryptPushRes();
                res3.isQueryDb = true;
                res3.value = '';
                res3.table = staticResource.get('Contact').awsTableName;
                //res3.dataId = ContactMap.get(ac.Contact__c).AWS_Data_Id__c;
                res3.dataId = (ContactMap == null || ContactMap.size() == 0) ?'':ContactMap.get(ac.Contact__c).AWS_Data_Id__c;
                res3.field = mmsp.get('Contact').get('Doctor_Division1__c').AWS_Field_API__c;
                resList3.add(res3);

                System.debug('Agency_Contact__c Name = ' +mmsp.get('Agency_Contact__c').get('Name').AWS_Field_API__c);
                System.debug('resList = ' + resList);
                EncryptPush.fieldsMapping.put(mmsp.get('Agency_Contact__c').get('Name').AWS_Field_API__c, resList);
                EncryptPush.fieldsMapping.put(mmsp.get('Agency_Contact__c').get('Type__c').AWS_Field_API__c, resList2);
                EncryptPush.fieldsMapping.put(mmsp.get('Agency_Contact__c').get('Doctor_Division1__c').AWS_Field_API__c, resList3);
                EncryptPushList.add(EncryptPush);
            }
            System.debug('EncryptPushListdataId = ' + JSON.serialize(EncryptPushList[0].dataId));
            System.debug('EncryptPushListsfRecordId = ' + JSON.serialize(EncryptPushList[0].sfRecordId));
            System.debug('EncryptPushListfieldsMapping = ' + JSON.serialize(EncryptPushList[0].fieldsMapping));
            //AWSServiceTool2.EncryptPushCore(JSON.serialize(scope),'Agency_Contact__c');
            if(!Test.isRunningTest()){
                AwsServiceTool2V2.EncryptPushCoreV2(Json.serialize(EncryptPushList),JSON.serialize(scope), 'Agency_Contact__c');
            }
            //zhj MEBG新方案改造 2022-11-28 end
        }      
    }

    global void execute(SchedulableContext SC) {
        system.debug('this query from schedule execute method:'+this.query);
        Id execBTId = Database.executeBatch(new SyncAccountContactToAWS(this.query,SC.getTriggerId(),this.ContactMap), 1);       
        system.debug('Batch Job Id:'+execBTId);
    }

    public static void assignOnceOneMinuteLater(List<Agency_Contact__c> acList,Map<Id,Contact> cm) {
        system.debug('ACList:'+JSON.serialize(acList));
        String hour = String.valueOf(Datetime.now().hour());
        String min = String.valueOf(Datetime.now().minute() + 1); 
        String ss = String.valueOf(Datetime.now().second());
        //parse to cron expression
        String nextFireTime = ss + ' ' + min + ' ' + hour + ' * * ?';
        //Prepare the soql to agency account
        String soqlForAgencyAccount = '';
        if(acList!=null && acList.size()>0){
            soqlForAgencyAccount = 'SELECT id,Doctor_Division1__c,Doctor_Division1_Encrypted__c,Name,Name_Encrypted__c,Type__c,Type_Encrypted__c,AWS_Data_Id__c,Contact__c, Contact__r.Doctor_Division1_Encrypted__c,Contact__r.LastName_Encrypted__c, Contact__r.Type_Encrypted__c FROM Agency_Contact__c WHERE id in ';
            List<String> acIds = new List<String>();
            for(Agency_Contact__c ac:acList ){
                acIds.add(ac.Id);
            }
            soqlForAgencyAccount = soqlForAgencyAccount +  '(\'' + String.join(acIds, '\', \'') + '\')';
        }
        system.debug('SOQL for agency:'+soqlForAgencyAccount);
        system.debug('cm  = '+cm);
        SyncAccountContactToAWS s = new SyncAccountContactToAWS(soqlForAgencyAccount,cm);
        try{
            System.schedule('SyncAccountContactToAWS:' + String.valueOf(Datetime.now()), nextFireTime, s);
        }catch(Exception e){
            system.debug('Exception from SyncAccountContactToAWS:'+e.getMessage());
        }      
    }

    global void finish(Database.BatchableContext BC) {
        system.debug('Finish batch job Id:'+BC.getJobId()); 
        AsyncApexJob a = [SELECT Id, Status, NumberOfErrors, JobItemsProcessed, TotalJobItems, CreatedBy.Email FROM AsyncApexJob WHERE Id = :BC.getJobId()];
        //then use the active job id and abort it
        system.abortJob(a.id);
        system.debug('Finish schedule job Id:'+scheduleId); 
        if(scheduleId!=null&&scheduleId!=''){
            system.abortJob(scheduleId);
        }
    }
}