@RestResource(urlMapping = '/NFM109/*')
global with sharing class NFM109Rest {

    public static List<String> emailMessages = new List<String>();

    public static Integer totalCount = 0; // 总件数
    public static Integer failedCount = 0; // 失败件数

    public NFM109Rest() { 

    }

    public class GeneralData {
        // public InspectionResult[] InspectionResult;
        public InspectionRequest InspectionRequest;
    }

    public class InspectionRequest {
        public InspectionResult InspectionResult;
        public NFMUtil.Monitoring Monitoring;
    }

    public class Failure {
        public String LocationGroup;
        public String Location;
        public String Phenomenon;
        public String Description;
        public String Cause;
        public String PaeFlag;
        public String EtqPart;
        public String EtqAsAnalyzed;
        public String EtqCause;
        public String FinalUniversal;
        public String FinalUniversalDesc;

        public String LocationGroupDesc;
        public String LocationDesc;
    }

    // 不使用
    public class Parts {
        public String ItemCode;
        public String Qty;
        public String BomCode;
    }

    // 不使用
    public class Quotation {
        public String RepairRank;
        public String CafeteriaFlag;
        // public String ActivityCode;
        public String[] ActivityCode;
        public Parts[] Parts;
    }

    public class IntakeInfo {
        public String PaeFlag;
        public String IntakeUniversal;
        public String IntakeUniversalDesc;
        public String NotReproduceFlag;
        public String NotReproduceIntakeUniversal; // 不使用
        public String NotReproduceIntakeUniversalDesc;
    }

    // 不使用
    public class Measure {
        public String CumulativeUses;
        public String CumulativeTimes;
    }

    public class InspectionResult {
        public String SAPRepairNotificationNo;
        public String ProductCode; // 不使用
        public String InspectionBranchNo; 
        public String InspectionDate;
        public String InspectionUser;
        public String InspectionUserInEnglish;
        public String InspectionResultFlag;
        public String InspectionComment;
        public String FailureCause;
        public String CafeteriaPlanFlag; // 不使用
        public String InspectionCategory;
        public String DomainCaption; // 不使用
        public Failure[] Failure;
        public Quotation[] Quotation;
        public String ThirdParty; 
        public IntakeInfo[] IntakeInfo;
        public String EtQManagementNo; // 不使用
        public Measure Measure;
    }

    @HttpPost
    global static void execute() {

        // 取得接口传输内容
        // {"InspectionRequest":{"InspectionResult":}}
        String strData = RestContext.request.requestBody.toString();
        GeneralData genData =  (GeneralData) JSON.deserializeStrict(strData, GeneralData.class);
        if (genData == null ) {
            return;
        }

        NFMUtil.Monitoring Monitoring = genData.InspectionRequest.Monitoring;
        // 日志相关
        if (Monitoring == null) {
            Monitoring = new NFMUtil.Monitoring();
            // return;
        }
        
        BatchIF_Log__c rowData = NFMUtil.saveRowData(Monitoring, 'NFM109', genData.InspectionRequest.InspectionResult);
        if (!String.isBlank(rowData.Log__c)) executefuture(rowData.Id);

        // JSONを戻す
        RestResponse res = RestContext.response;
        res.addHeader('Content-Type', 'application/json');
        res.statusCode = 200;
        String jsonResponse = '{"status": "Success", "Message":""}';
        res.responseBody = blob.valueOf(jsonResponse);
        return;
    }

    @future
    global static void executefuture(String rowData_Id) {
        main(rowData_Id);
    }

    global static void main(String rowData_Id) {
        // 错误日志
        Integer batch_retry_max_cnt = Integer.valueOf(System.Label.batch_retry_max_cnt);
        BatchIF_Log__c rowData = [Select Id, Name, Log__c, ErrorLog__c, Log2__c, Log3__c, Log4__c, Log5__c, Log6__c, Log7__c, Log8__c, Log9__c, Log10__c, Log11__c, Log12__c, MessageGroupNumber__c, retry_cnt__c from BatchIF_Log__c where RowDataFlg__c = true and Id = :rowData_Id];
        String logstr = rowData.MessageGroupNumber__c + ' start!\n';
        BatchIF_Log__c iflog = new BatchIF_Log__c();
        iflog.Type__c = 'NFM109';
        iflog.MessageGroupNumber__c = rowData.MessageGroupNumber__c;
        iflog.Log__c = logstr;
        iflog.ErrorLog__c = '';
        insert iflog;
                
        Savepoint sp = Database.setSavepoint();
        try {

            // 取得日志中存储的数据
            String rowDataStr = NFMUtil.getRowDataStr(rowData);
            InspectionResult logResult = (InspectionResult) JSON.deserialize(rowDataStr, InspectionResult.class);
            
            List<InspectionResult> inspectionResults = new List<InspectionResult>();
            inspectionResults.add(logResult);

            // 存储所有的SAP修理单号
            List<String> SAPNos = new List<String>();
            for (InspectionResult ins : inspectionResults) {
                SAPNos.add(ins.SAPRepairNotificationNo);
                totalCount++;
            }
            
            // 查询对应的修理
            Map<Id,Repair__c> res = new Map<Id,Repair__c>([select id,name,SAP_Service_Repair_No__c,IISE_confirmed_day__c,
                                                               IISE_Inspection_Branch_Zero__c,IISE_Inspection_Branch_Three__c,
                                                               IISE_confirmed_person__c,IISE_confirmed_person_en__c,
                                                               InspectionCategory_Zero__c,InspectionCategory_Three__c,
                                                               ASReportedCodeAC__c,PAE_codez__c
                                                               from repair__c 
                                                               where SAP_Service_Repair_No__c in :SAPNos and SAP_Service_Repair_No__c != null]);

            Map<String,Repair__c> resMap = new Map<String,Repair__c>();
            for (Repair__c re : res.values()) {
                resMap.put(re.SAP_Service_Repair_No__c,re);
            }

            // 需要修改的修理数据
            Map<Id,Repair__c> updateRepairs = new Map<Id,Repair__c>();

            // 新建PAE判定记录
            List<PAE_DecisionRecord__c> newPAEDecisionRecordList = new List<PAE_DecisionRecord__c>();

            // 新建PAE判定记录明细
            List<PAE_DecisionRecordDetail__c> newPAEDetailList = new List<PAE_DecisionRecordDetail__c>();

            // 通过intakeinfo更新的PAE判定记录明细
            List<PAE_DecisionRecordDetail__c> updatePAEDetails = new List<PAE_DecisionRecordDetail__c>();

            // 需要将状态更新至 取消 的PAE判定记录明细
            // List<PAE_DecisionRecordDetail__c> invalidPAEDetails = new List<PAE_DecisionRecordDetail__c>();

            Map<String, List<IntakeInfo>> repairInfoMap = new Map<String, List<IntakeInfo>>();
            // 修理对应的PAE判定记录 final
            List<PAE_DecisionRecord__c> dbPAEDecisionRecordList =  [select id,PAE_reappear_confirm__c,LastModifiedDate,PAE_Repair__c 
                                                                        from PAE_DecisionRecord__c
                                                                        where PAE_Repair__c in :res.values() 
                                                                        and recordType.DeveloperName = 'ASACDecision'
                                                                        order by LastModifiedDate desc];

            // 修理对应的最新Final的PAE判定记录
            Map<String,PAE_DecisionRecord__c> repPaeRecordMap = new Map<String,PAE_DecisionRecord__c>();
            for (PAE_DecisionRecord__c ele : dbPAEDecisionRecordList) {
                if (repPaeRecordMap.get(ele.PAE_Repair__c) == null) {
                    repPaeRecordMap.put(ele.PAE_Repair__c,ele);
                }
            }      
            
            List<PAE_DecisionRecordDetail__c> repPAEDetailList =  [select id,PAED_ManagementCode__c,PAED_RCAC__c,PAED_Status__c,InspectionCategory109__c,
                                                                       PAE_Judge__c,PAE_DecisionRecordD__c,PAED_Repair__c,PAED_Repair__r.name,
                                                                       LocationGroup__c,Location__c,Phenomenon__c,Description__c,Cause__c,EtqPart__c,
                                                                       EtqAsAnalyzed__c,EtqCause__c,FinalUniversalDesc__c 
                                                                       from PAE_DecisionRecordDetail__c 
                                                                       where PAED_Repair__c in :res.values()
                                                                       and (InspectionCategory109__c = '0' or InspectionCategory109__c = '3')
                                                                       and PAED_Status__c = '有效'
                                                                       //add by rentx 2020-11-02 intake时不操作,final时取消
                                                                       and PAED_RCAC__c = 'Final'];
            // 修理对应的由接口创建的0或3的PAE判定记录明细
            Map<String,List<PAE_DecisionRecordDetail__c>> repPaeDetailZeroMap = new Map<String,List<PAE_DecisionRecordDetail__c>>();
            // Map<String,List<PAE_DecisionRecordDetail__c>> repPaeDetailThreeMap = new Map<String,List<PAE_DecisionRecordDetail__c>>();
            for (PAE_DecisionRecordDetail__c ele : repPAEDetailList) {
                if (ele.InspectionCategory109__c == '0') {
                    List<PAE_DecisionRecordDetail__c> details = repPaeDetailZeroMap.get(ele.PAED_Repair__c);
                    if (details == null) {
                        details = new List<PAE_DecisionRecordDetail__c>();
                    }
                    details.add(ele);
                    repPaeDetailZeroMap.put(ele.PAED_Repair__c,details);
                }
                // else{
                //     List<PAE_DecisionRecordDetail__c> details = repPaeDetailThreeMap.get(ele.PAED_Repair__c);
                //     if (details == null) {
                //         details = new List<PAE_DecisionRecordDetail__c>();
                //     }
                //     details.add(ele);
                //     repPaeDetailThreeMap.put(ele.PAED_Repair__c,details);
                // }
            }
            List<String> updateRepairCodeIds = new List<String>();
            for (InspectionResult ins : inspectionResults) {

                // 拿到每一条对应的修理数据 
                Repair__c re = resMap.get(ins.SAPRepairNotificationNo);    
                // SAPRepairNotificationNo作为Key检索SFDC的修理单。检索不到的时候报错。继续处理下一单。
                if (re == null) {
                    iflog.ErrorLog__c += 'Error! SAP_Service_Repair_No__c[' + ins.SAPRepairNotificationNo + ']  is Not Found. This Repar is skipped.\n';
                    // 20201210 为了报错后方便查找需要再执行的数据
                    rowData.ErrorLog__c = 'Error! SAP_Service_Repair_No__c[' + ins.SAPRepairNotificationNo + ']  is Not Found. This Repar is skipped.\n';
                    failedCount++;
                    continue;
                }else{
                    rowData.ErrorLog__c = null;
                }

                // 更新修理
                Integer inspectionDateYear =  Integer.valueOf(ins.InspectionDate.substring(0,4));
                Integer inspectionDateMonth = Integer.valueOf(ins.InspectionDate.substring(4,6));
                Integer inspectionDateDay = Integer.valueOf(ins.InspectionDate.substring(6,8));
                re.IISE_confirmed_day__c = Date.newInstance(inspectionDateYear,inspectionDateMonth,inspectionDateDay);
                
                re.IISE_confirmed_person__c = ins.InspectionUser;
                System.debug('IISE_confirmed_person__c +++++ ' + re.IISE_confirmed_person__c);
                
                // FinalInfo收到的时候需要更细修理画面的
                // 20201102 gzw bug对应 空报错问题 start
                if (ins.Failure != null &&  ins.Failure.size() > 0) {
                // if (ins.Failure.size() > 0) {
                // 20201102 gzw bug对应 空报错问题 end
                    // - OCSM Coding确认日 
                    // - OCSM Coding确认者
                    // re.OCSM_RC_CordingUser__c = re.IISE_confirmed_person__c;
                    re.OCSM_RC_CordingDate__c = re.IISE_confirmed_day__c;
                    // Universal Failure Code
                    // updateRepairUniversalFailureCode(re);
                    updateRepairCodeIds.add(re.Id);
                }
                re.IISE_confirmed_person_en__c = ins.InspectionUserInEnglish;
                re.InspectionComment__c = ins.InspectionComment;
                re.InspectionResultFlag__c = ins.InspectionResultFlag;
                re.InspectionFailureCause__c = ins.FailureCause;
                re.ThirdPartyRepair__c = ins.ThirdParty == 'true' ? true : false;


                updateRepairs.put(re.Id,re);

                // 最新的一条PAE判定记录
                PAE_DecisionRecord__c lastModified = repPaeRecordMap.get(re.Id);

                // SAPRepairNotificationNo和InspectionCategory作为Key处理。如果Key一致的话，看InspectionBranchNo。
                if (re.InspectionCategory_Zero__c == ins.InspectionCategory || re.InspectionCategory_Three__c == ins.InspectionCategory){
                    if ('0'.equals(ins.InspectionCategory)) {
                        // 更新
                        if (String.isNotBlank(re.IISE_Inspection_Branch_Zero__c) && (Integer.valueOf(ins.InspectionBranchNo) > Integer.valueOf(re.IISE_Inspection_Branch_Zero__c))) {
                            // 20201102 add by gzw 不管有没有IntakeInfo，Intake信息不取消。SFDC的Intake信息必须保留的 start
                            // 取消 PAE判定记录明细为0的
                            List<PAE_DecisionRecordDetail__c> detailZeroList = repPaeDetailZeroMap.get(re.Id);
                            if (detailZeroList != null) {
                                for(PAE_DecisionRecordDetail__c detail : detailZeroList){
                                    detail.PAED_Status__c = '取消';
                                    // invalidPAEDetails.add(detail);
                                    // InspectionBranchNo大于现有的数字并InspectionCategory=0的数据来的时候，需要填写下列字段
                                    // 取消者
                                    // detail.PAED_Nullifier__c = re.IISE_confirmed_person__c;
                                    // 取消日
                                    // detail.PAED_CancellationDate__c = re.IISE_confirmed_day__c;
                                    detail.isInterfaceCreate__c = true;
                                    updatePAEDetails.add(detail);
                                }
                            }
                            // 20201102 add by gzw 不管有没有IntakeInfo，Intake信息不取消。SFDC的Intake信息必须保留的 end
                            createNewPAEDeatil(re,ins.Failure,lastModified,newPAEDecisionRecordList,newPAEDetailList,ins.InspectionCategory);
                        }else{
                            // 新建
                            if (String.isBlank(re.IISE_Inspection_Branch_Zero__c)) {
                                createNewPAEDeatil(re,ins.Failure,lastModified,newPAEDecisionRecordList,newPAEDetailList,ins.InspectionCategory);
                            }    
                        }
                    }else if ('3'.equals(ins.InspectionCategory)) {
                        // 更新
                        if (String.isNotBlank(re.IISE_Inspection_Branch_Three__c) && (Integer.valueOf(ins.InspectionBranchNo) > Integer.valueOf(re.IISE_Inspection_Branch_Three__c))) {
                            // 取消 PAE判定记录明细为3的
                            // List<PAE_DecisionRecordDetail__c> detailThreeList = repPaeDetailThreeMap.get(re.Id);
                            // for(PAE_DecisionRecordDetail__c detail : detailThreeList){
                            //     detail.PAED_Status__c = '取消';
                            //     invalidPAEDetails.add(detail);
                            // }
                            
                            createNewPAEDeatil(re,ins.Failure,lastModified,newPAEDecisionRecordList,newPAEDetailList,ins.InspectionCategory);
                        }else{
                            // 新建    
                            if (String.isBlank(re.IISE_Inspection_Branch_Three__c)) {
                                createNewPAEDeatil(re,ins.Failure,lastModified,newPAEDecisionRecordList,newPAEDetailList,ins.InspectionCategory);
                            }
                        }
                    }
                    
                } else {
                    createNewPAEDeatil(re,ins.Failure,lastModified,newPAEDecisionRecordList,newPAEDetailList,ins.InspectionCategory);
                }

                if ('0'.equals(ins.InspectionCategory)) {
                    re.InspectionCategory_Zero__c = ins.InspectionCategory;
                    re.IISE_Inspection_Branch_Zero__c = ins.InspectionBranchNo;
                }else if ('3'.equals(ins.InspectionCategory)) {
                    re.InspectionCategory_Three__c = ins.InspectionCategory;
                    re.IISE_Inspection_Branch_Three__c = ins.InspectionBranchNo;
                }

                // 更新PAE判定记录明细 start
                // 拿到每条数据中的IntakeInfo信息 数组
                if (ins.IntakeInfo != null && ins.IntakeInfo.size() > 0) {
                    repairInfoMap.put(re.Id, ins.IntakeInfo);
                }

            }

            // 作为Key检索SFDC的修理单下面的有效的Intake的PAE判定记录明细,检索不到的时候报错,继续处理下一条Intake信息。
            // 符合条件的PAE判定记录明细
            List<PAE_DecisionRecordDetail__c> PAEDetails = [select id,PAED_ManagementCode__c,PAED_RCAC__c,PAED_Status__c,
                                                                PAE_Judge__c,PAE_DecisionRecordD__c,PAED_Repair__c,PAED_Repair__r.name,
                                                                LocationGroup__c,Location__c,Phenomenon__c,Description__c,Cause__c,EtqPart__c,
                                                                EtqAsAnalyzed__c,EtqCause__c,FinalUniversalDesc__c,PAED_Reappear_Result__c 
                                                                from PAE_DecisionRecordDetail__c
                                                                where PAED_Repair__c = :res.values() 
                                                                and PAED_Status__c = '有效'
                                                                // 20210601 gzw 取判断最新记录
                                                                and PAE_DecisionRecordD__r.Last_NewRecord__c = true
                                                                and PAED_RCAC__c = 'Intake'];

            
            Map<String,List<PAE_DecisionRecordDetail__c>> PAEDetailMap = new Map<String,List<PAE_DecisionRecordDetail__c>>();
            for(PAE_DecisionRecordDetail__c PAEDetail : PAEDetails){
                List<PAE_DecisionRecordDetail__c> codeDetails = PAEDetailMap.get(PAEDetail.PAED_Repair__c);
                if (codeDetails == null) {
                    codeDetails = new List<PAE_DecisionRecordDetail__c>();
                }
                codeDetails.add(PAEDetail);
                PAEDetailMap.put(PAEDetail.PAED_Repair__c,codeDetails);
            }   
            
            // System.debug('repairInfoMap'+repairInfoMap);
            // System.debug('PAEDetails'+PAEDetails);
            // System.debug('PAEDetailMap'+PAEDetailMap);
            for (String repId : repairInfoMap.keySet()) { 
                List<IntakeInfo> infos = repairInfoMap.get(repId);
                if (infos != null && infos.size() > 0) {
                    for (IntakeInfo intake : infos) {
                        Boolean flag = false;
                        List<PAE_DecisionRecordDetail__c> repPAEDetails =  PAEDetailMap.get(repId);
                        if (repPAEDetails != null && repPAEDetails.size() > 0) {
                            for (PAE_DecisionRecordDetail__c PAEDetail : repPAEDetails) { 
                                if (intake.IntakeUniversal == PAEDetail.PAED_ManagementCode__c) {
                                    PAEDetail.IntakeUniversalDesc__c = intake.IntakeUniversalDesc;
                                    // if "true" then "不再现" else "再现"
                                    // true：PAE, false：Non PAE, unknown：Unknown
                                    // PAEDetail.PAE_Judge__c = intake.PaeFlag == 'true' ? 'PAE' : 'nonPAE'; 
                                    // NFM109来的时候，不更新Intake的PAE判定的话 start
                                    // switch on intake.PaeFlag {
                                    //     when 'true'{
                                    //         PAEDetail.PAE_Judge__c = 'PAE';
                                    //     }
                                    //     when 'false'{
                                    //         PAEDetail.PAE_Judge__c = 'nonPAE';
                                    //     }
                                    //     when 'unknown'{
                                    //         PAEDetail.PAE_Judge__c = 'Unknown';
                                    //     }
                                    // }
                                    // NFM109来的时候，不更新Intake的PAE判定的话 end
                                    PAEDetail.PAED_Reappear_Result__c = intake.NotReproduceFlag == 'True' ? '不再現' : '再現';
                                    // 用于页面 是否可操作
                                    PAEDetail.isInterfaceCreate__c = true;
                                    // Intake编辑 不再现的时候需要填写下列字段
                                    if (intake.NotReproduceFlag == 'True') {
                                        // PAEDetail.PAED_ResultAffirmant__c = updateRepairs.get(repId).IISE_confirmed_person__c;
                                        // 课题94 NFM109（a001s000001Xtei）处理的时候，没更新Intake的PAE判定明细的【不再現結果確認者】。应该更新的。
                                        // 新建文本存储不再現結果確認者
                                        PAEDetail.PAED_ResultAffirmant_txt__c = updateRepairs.get(repId).IISE_confirmed_person__c;
                                        PAEDetail.PAED_ResultConfirmationDate__c = updateRepairs.get(repId).IISE_confirmed_day__c;
                                    }
                                    PAEDetail.NotReproduceIntakeUniversalDesc__c = intake.NotReproduceIntakeUniversalDesc;
                                    // System.debug('PAEDetail++'+PAEDetail);
                                    updatePAEDetails.add(PAEDetail);
                                    flag = true;
                                }
                            }
                        }
                        if (!flag) {
                            iflog.ErrorLog__c += 'Warning! Repair__c = ['+repId+'] ---> PAE_DecisionRecordDetail__c[' + intake.IntakeUniversal + ']  is Not Found. This PAE_DecisionRecordDetail__c is skipped.\n';
                            failedCount++;
                        }
                    }
                }
            }
            // 更新PAE判定记录明细 end


            // 插入新创建的PAE判定记录
            insert newPAEDecisionRecordList;
            // upsert newPAEDecisionRecordList;

            // 将新建PAE判定记录明细的关联到PAE判定记录
            for(PAE_DecisionRecord__c paeRecord : newPAEDecisionRecordList){
                for(PAE_DecisionRecordDetail__c paeDetail : newPAEDetailList){
                    if (paeDetail.PAED_Repair__c == paeRecord.PAE_Repair__c) {
                        paeDetail.PAE_DecisionRecordD__c = paeRecord.Id;
                    }
                }
            }

            // 添加新建PAE判定记录明细
            insert newPAEDetailList;
            // 更新PAE判定记录明细(intakeinfo or PAED_Status__c = '取消')
            update updatePAEDetails;  
            // 更新被取消的PAE判定记录明细
            // update invalidPAEDetails;
           

            // 更新再现结果 start
            // 更新到修理上
            List<PAE_DecisionRecord__c> lastModifiedRecordList = [select id,name,PAEDetail_reappear_confirm__c,PAE_Repair__c 
                                                        from PAE_DecisionRecord__c 
                                                        where PAE_Repair__c in :updateRepairs.keySet()
                                                        and RecordType.DeveloperName = 'ASRCDecision' 
                                                        order by LastModifiedDate desc];
            Map<String,PAE_DecisionRecord__c> lastModifiedRecordMap = new Map<String,PAE_DecisionRecord__c>();
            for (PAE_DecisionRecord__c record : lastModifiedRecordList) {
                if (lastModifiedRecordMap.get(record.PAE_Repair__c) == null) {
                    lastModifiedRecordMap.put(record.PAE_Repair__c,record);
                }
            }                                                        

            for (String repId : lastModifiedRecordMap.keySet()) {
                if (updateRepairs.get(repId) != null) {
                    updateRepairs.get(repId).PAE_reappear_confirm__c = lastModifiedRecordMap.get(repId).PAEDetail_reappear_confirm__c;
                }
            }
            // 更新再现结果 end

            // 更新Universal Failure Code  start
            Set<String> paeIds = new Set<String>();
            lastModifiedRecordMap = new Map<String,PAE_DecisionRecord__c>();
            lastModifiedRecordList = [select id,name,PAEDetail_reappear_confirm__c,PAE_Repair__c 
                                    from PAE_DecisionRecord__c 
                                    // where PAE_Repair__c in :updateRepairCodeIds
                                    where PAE_Repair__c in :updateRepairs.keySet()
                                    and RecordType.DeveloperName = 'ASRCDecision' 
                                    order by LastModifiedDate desc];
            for (PAE_DecisionRecord__c record : lastModifiedRecordList) {
                if (lastModifiedRecordMap.get(record.PAE_Repair__c) == null) {
                    paeIds.add(record.Id);
                    lastModifiedRecordMap.put(record.PAE_Repair__c,record);
                }
            }                 
            Map<String,List<PAE_DecisionRecord__c>> lastModifiedRecordMap2 = new Map<String,List<PAE_DecisionRecord__c>>();
            for (String repId : lastModifiedRecordMap.keySet()) {
                List<PAE_DecisionRecord__c> decisionRecordList = new List<PAE_DecisionRecord__c>();
                decisionRecordList.add(lastModifiedRecordMap.get(repId));
                lastModifiedRecordMap2.put(repId,decisionRecordList);
            }

            lastModifiedRecordList = [select id,name,PAEDetail_reappear_confirm__c,PAE_Repair__c 
                                    from PAE_DecisionRecord__c 
                                    // where PAE_Repair__c in :updateRepairCodeIds
                                    where PAE_Repair__c in :updateRepairs.keySet()
                                    and RecordType.DeveloperName = 'ASACDecision' 
                                    order by LastModifiedDate desc];
            lastModifiedRecordMap = new Map<String,PAE_DecisionRecord__c>();
            for (PAE_DecisionRecord__c record : lastModifiedRecordList) {
                if (lastModifiedRecordMap.get(record.PAE_Repair__c) == null) {
                    paeIds.add(record.Id);
                    lastModifiedRecordMap.put(record.PAE_Repair__c,record);
                }
            } 

            for (String repId : lastModifiedRecordMap.keySet()) {
                List<PAE_DecisionRecord__c> decisionRecordList =  lastModifiedRecordMap2.get(repId);
                if (decisionRecordList == null) {
                    decisionRecordList = new List<PAE_DecisionRecord__c>();
                }
                decisionRecordList.add(lastModifiedRecordMap.get(repId));
                lastModifiedRecordMap2.put(repId,decisionRecordList);
            }

            System.debug('++++++: '+ paeIds);
            List<PAE_DecisionRecordDetail__c> updateRepairCode = [select id,name,PAED_RCAC__c,PAED_ManagementCode__c,
                                                                Final_universal_code__c,PAED_Repair__c,PAED_Reappear_Result__c
                                                                from PAE_DecisionRecordDetail__c 
                                                                // where PAED_Repair__c in :lastModifiedRecordMap2.keySet()
                                                                where PAE_DecisionRecordD__c in :paeIds
                                                                and PAED_Status__c = '有效' order by PAED_RCAC__c desc];

            Map<String,List<PAE_DecisionRecordDetail__c>> recordDetailMap = new Map<String,List<PAE_DecisionRecordDetail__c>>();                                                         
            for (PAE_DecisionRecordDetail__c detail : updateRepairCode) {
                List<PAE_DecisionRecordDetail__c> recordDetails = recordDetailMap.get(detail.PAED_Repair__c);
                if (recordDetails == null) {
                    recordDetails = new List<PAE_DecisionRecordDetail__c>();
                }
                recordDetails.add(detail);
                recordDetailMap.put(detail.PAED_Repair__c,recordDetails);
            }           
            // System.debug('recordDetailMap'+recordDetailMap);                                                   

            Map<String,String> finalUniversalCodeMap = new Map<String,String>();
            for (String repId : recordDetailMap.keySet()) {
                List<PAE_DecisionRecordDetail__c> detailList = recordDetailMap.get(repId);
                String codes = '';
                String fcodes = '';
                String codeZ = '';
                for (PAE_DecisionRecordDetail__c detail : detailList) {
                    if ('Intake'.equals(detail.PAED_RCAC__c)) {
                        if (detail.PAED_Reappear_Result__c == '不再現') {
                            // WLIG-BWMB4S gzw start
                            String pmcode = detail.PAED_ManagementCode__c.trim();
                            if(pmcode.length() == 3 && (pmcode.endsWith('V') || pmcode.endsWith('W') || pmcode.endsWith('X') || pmcode.endsWith('Y'))){
                                codes += pmcode.substring(0,pmcode.length() - 1) + 'Z,';
                                codeZ += pmcode.substring(0,pmcode.length() - 1) + 'Z,';
                            }else{
                                codes += pmcode + 'Z,';
                                codeZ  += pmcode + 'Z,';
                            }
                            // codes += detail.PAED_ManagementCode__c + 'Z,';
                            // codeZ  += detail.PAED_ManagementCode__c + 'Z,';
                            // WLIG-BWMB4S gzw end
                        }
                    } else {
                        // 20202204 高章伟 空白code不处理 start
                        if (String.isNotBlank(detail.PAED_ManagementCode__c)) {
                            codes += detail.PAED_ManagementCode__c + ',';
                            fcodes += detail.PAED_ManagementCode__c + ',';
                        }
                        // 20202204 高章伟 空白code不处理 end
                    }
                }
                if (codes.endsWith(',')) {
                    codes = codes.substring(0,codes.length() - 1);
                }
                if (fcodes.endsWith(',')) {
                    fcodes = fcodes.substring(0,fcodes.length() - 1);
                }
                if (codeZ.endsWith(',')) {
                    codeZ = codeZ.substring(0,codeZ.length() - 1);
                }
                // System.debug('repId++'+repId+'  codes'+codes);
                updateRepairs.get(repId).ASReportedCodeAC__c = codes;
                updateRepairs.get(repId).PAE_codez__c = codeZ;
                updateRepairs.get(repId).PAE_temp_final_code__c = fcodes;
            }
            // 更新Universal Failure Code  end




            // 更新修理
            update updateRepairs.values();

            update iflog;
            rowData.retry_cnt__c = 0;
        } catch (Exception ex) {
            // エラーが発生した場合
            Database.rollback(sp);
            System.debug(Logginglevel.ERROR, 'NFM109_' + rowData.MessageGroupNumber__c + ':' + ex.getMessage());
            System.debug(Logginglevel.ERROR, 'NFM109_' + rowData.MessageGroupNumber__c + ':' + ex.getStackTraceString());
            logstr += '\n' + ex.getMessage();
            iflog.ErrorLog__c = ex.getMessage() + '\n' + ex.getStackTraceString() + '\n' + iflog.ErrorLog__c;
            if (rowData.retry_cnt__c == null) rowData.retry_cnt__c = 0;
            if (rowData.retry_cnt__c < batch_retry_max_cnt) {
                rowData.retry_cnt__c++;
                LogAutoSendSchedule.assignOneMinute();
            }
            if (rowData.retry_cnt__c >= batch_retry_max_cnt) {
                rowData.ErrorLog__c = ex.getMessage() + '\n' + ex.getStackTraceString() + '\n' + rowData.ErrorLog__c + '错误次数已经超过自动收信设定的最大次数，请手动收信';
            }
            emailMessages.add('失败日志ID为：' + iflog.Id);
        }

        update rowData;
        iflog.Log__c = logstr;
        if (rowData.retry_cnt__c == 0) {
            iflog.retry_cnt__c = 0;
        }
        if (iflog.Log__c.length() > 131072) {
            iflog.Log__c = iflog.Log__c.subString(0, 131065) + ' ...';
        }
        if (iflog.ErrorLog__c.length() > 32768) {
            iflog.ErrorLog__c = iflog.ErrorLog__c.subString(0, 32760) + ' ...';
        }
        update iflog;
    }

    public static void createNewPAEDeatil(Repair__c re, Failure[] failures,PAE_DecisionRecord__c  paeRecord,List<PAE_DecisionRecord__c> newPAEDecisionRecordList ,List<PAE_DecisionRecordDetail__c> newPAEDetailList,String category){
       
        if (failures != null && failures.size() > 0) {
            PAE_DecisionRecord__c newPAERecord = paeRecord;
            if (paeRecord == null) {
                // 创建PAE判定记录 需要关联到修理
                newPAERecord = new PAE_DecisionRecord__c();
                newPAERecord.PAE_Repair__c = re.Id;
                newPAERecord.RecordTypeId = Schema.SObjectType.PAE_DecisionRecord__c.getRecordTypeInfosByDeveloperName().get('ASACDecision').getRecordTypeId();
                newPAEDecisionRecordList.add(newPAERecord);
                // System.debug('创建PAE判定记录'+newPAERecord);
            }

            // 一个Failure信息创建一个Final的PAE判定记录明细，关联到PAE判定记录。
            for (Failure fa: failures) {
                PAE_DecisionRecordDetail__c newPAEDetail = new PAE_DecisionRecordDetail__c();
                // newPAEDetail.LocationGroup__c = fa.LocationGroup;
                newPAEDetail.LocationGroup__c = fa.LocationGroupDesc;
                // newPAEDetail.Location__c = fa.Location;
                newPAEDetail.Location__c = fa.LocationDesc;
                newPAEDetail.Phenomenon__c = fa.Phenomenon;
                newPAEDetail.Description__c = fa.Description;
                newPAEDetail.Cause__c = fa.Cause;
                // if "true" then "PAE" else "nonPAE"
                // true：PAE, false：Non PAE, unknown：Unknown
                // newPAEDetail.PAE_Judge__c = fa.PaeFlag == 'true' ? 'PAE' : 'nonPAE';
                switch on fa.PaeFlag {
                    when 'true'{
                        newPAEDetail.PAE_Judge__c = 'PAE';
                    }
                    when 'false'{
                        newPAEDetail.PAE_Judge__c = 'nonPAE';
                    }
                    when 'unknown'{
                        newPAEDetail.PAE_Judge__c = 'Unknown';
                    }
                }
                newPAEDetail.EtqPart__c = fa.EtqPart;
                newPAEDetail.EtqAsAnalyzed__c = fa.EtqAsAnalyzed;
                newPAEDetail.EtqCause__c = fa.EtqCause;
                newPAEDetail.PAED_ManagementCode__c = fa.FinalUniversal;
                newPAEDetail.FinalUniversalDesc__c = fa.FinalUniversalDesc;
                // 创建一个Final的PAE判定记录明细
                newPAEDetail.PAED_RCAC__c = 'Final';
                newPAEDetail.RecordTypeId = Schema.SObjectType.PAE_DecisionRecordDetail__c.getRecordTypeInfosByDeveloperName().get('final').getRecordTypeId();

                // 关联到PAE判定记录
                newPAEDetail.PAE_DecisionRecordD__c = newPAERecord.Id;
                // 关联到修理
                newPAEDetail.PAED_Repair__c = re.Id;
                newPAEDetail.PAED_Status__c = '有效';

                // 如果是之前的记录则不可修改
                newPAEDetail.PAE_is_save__c = '1';

                // 确认日，确认者
                // newPAEDetail.PAED_Affirmant__c = re.IISE_confirmed_person__c;
                newPAEDetail.PAED_ConfirmationDate__c = re.IISE_confirmed_day__c;

                // 通过接口新建的数据 添加一个标记
                newPAEDetail.isInterfaceCreate__c = true;
                newPAEDetail.InspectionCategory109__c = category;

                newPAEDetailList.add(newPAEDetail);   
                // System.debug('创建PAE判定记录明细++'+newPAEDetail);
            }
        }
    }

}