global class rollupToRepairBatch implements Database.Batchable<sObject>, Database.Stateful {
    public String query;

    global Integer totalCount = 0; // 总件数
    global Integer failedCount = 0;
    global List<String> emailMessages = new List<String>();
    public List<Id> repairId;
    public boolean isAll = false;

    global rollupToRepairBatch(List<Id> repairId) {
        this.repairId = repairId;
        this.isAll = true;

    }

    global rollupToRepairBatch(String query) {
        this.query = query;
    }

    global rollupToRepairBatch() {
    }
    global rollupToRepairBatch(boolean isAll) {
        this.isAll = isAll;
    }


    global Database.QueryLocator start(Database.BatchableContext bc) {
        // 20221110 ljh 优化 start
        Date st = Date.today().addMonths(-36);
        Datetime startDatetime = Datetime.newInstance(st.year(), st.month(), st.day(), 8, 0, 0);
        // 20221110 ljh 优化 end
        if (repairId != null && repairId.size() > 0) {
            return Database.getQueryLocator(
                       [select Id,
                        if_Rental_Apply__c ,
                        Offer_Rental_New__c,
                        Request_approval_day__c,
                        Bollow_Date__c
                        from repair__c
                        where Id in :repairId]);
        } else if (isAll) {
            return Database.getQueryLocator(
                       [select Id ,
                        if_Rental_Apply__c ,
                        Offer_Rental_New__c,
                        Request_approval_day__c,
                        Bollow_Date__c
                        from repair__c
                       ]);
        } else {
            // 20221110 ljh 优化 start
            // return Database.getQueryLocator(
            //            [select Id ,
            //             if_Rental_Apply__c ,
            //             Offer_Rental_New__c,
            //             Request_approval_day__c,
            //             Bollow_Date__c
            //             from repair__c
            //             where Repair_Completed_Date__c = null Or
            //                     Repair_Completed_Date__c >= :
            //                     Date.today().addMonths(-12)
            //            ]);
            return Database.getQueryLocator(
                       [select Id ,
                        if_Rental_Apply__c ,
                        Offer_Rental_New__c,
                        Request_approval_day__c,
                        Bollow_Date__c
                        from repair__c
                        where Status1__c  != '0.取消' 
                        and Status1__c   != '0.删除' 
                        and Status1__c != '5.完毕'
                        and (
                        (Repair_Completed_Date__c = null and CreatedDate > :startDatetime)
                         Or Repair_Completed_Date__c >= :Date.today().addMonths(-12)
                        )
                       ]);
            // 20221110 ljh 优化 end
        }
    }

    global void execute(Database.BatchableContext BC, List<repair__c> repairList) {
        Savepoint sp = Database.setSavepoint();

        map<ID, repair__c> OldRepairMap = new Map<ID, repair__c>();
        map<ID, repair__c> updateRepairMap = new Map<ID, repair__c>();
        for (Repair__c tempRepair : repairList ) {
            OldRepairMap.put(tempRepair.id, tempRepair);
            Repair__c newRepair = new Repair__c();
            newRepair.id = tempRepair.id;
            newRepair.if_Rental_Apply__c = false;
            newRepair.Offer_Rental_New__c = false;
            newRepair.Request_approval_day__c = null;
            newRepair.Bollow_Date__c = null;

            updateRepairMap.put(tempRepair.id, newRepair);
        }
        // 检索备品借出申请
        List<Rental_Apply__c> raList = [SELECT Id, Repair__c,
                                        Request_approval_day__c,
                                        Cancel_Reason__c,
                                        Bollow_Date__c
                                        FROM Rental_Apply__c
                                        WHERE (Repair__c IN :repairList
                                               AND Request_approval_day__c != null
                                               AND Cancel_Reason__c != '主动取消')
                                        OR (Repair__c IN :repairList
                                            AND Bollow_Date__c != null) ];
        // 汇总备品借出申请内容到修理
        if (raList != null && raList.size() > 0) {
            for (Rental_Apply__c ra : raList) {
                if (updateRepairMap.containsKey(ra.Repair__c)) {
                    Repair__c rep = updateRepairMap.get(ra.Repair__c);
                    if (ra.Request_approval_day__c != null &&
                            (
                                ra.Cancel_Reason__c == null ||
                                !ra.Cancel_Reason__c.equals('主动取消')
                            )
                       ) {
                        rep.if_Rental_Apply__c = true;
                        //保存最新的申请日期
                        rep.Request_approval_day__c =
                            rep.Request_approval_day__c ==null
                            ||ra.Request_approval_day__c > rep.Request_approval_day__c ?
                            ra.Request_approval_day__c : rep.Request_approval_day__c;
                    }

                    if (ra.Bollow_Date__c != null ) {
                        rep.Offer_Rental_New__c = true;
                        //保存最新的出库日
                        rep.Bollow_Date__c =
                            rep.Bollow_Date__c ==null
                            ||ra.Bollow_Date__c > rep.Bollow_Date__c ?
                            ra.Bollow_Date__c : rep.Bollow_Date__c;

                        
                    }
                }
            }
        }
        // 对比前后内容，如果没有发生变化，那么就从需要更新的数据中移除
        for (repair__c newRepair : OldRepairMap.values()) {
            repair__c OldRepair = updateRepairMap.get(newRepair.id);
            if (newRepair.if_Rental_Apply__c == OldRepair.if_Rental_Apply__c
                    && newRepair.Offer_Rental_New__c == OldRepair.Offer_Rental_New__c
                    && newRepair.Request_approval_day__c == OldRepair.Request_approval_day__c
                    && newRepair.Bollow_Date__c == OldRepair.Bollow_Date__c
               ) {
                updateRepairMap.remove(newRepair.id);
            }
        }

        // 更新发生变化的修理
        Database.SaveResult[] updateRepairResult = Database.update(updateRepairMap.values(), false);
        for (Database.SaveResult lsrChild : updateRepairResult ) {
            totalCount += 1;
            if ( !lsrChild.isSuccess() ) {
                failedCount += 1;
            }
        }

    }

    global void finish(Database.BatchableContext BC) {
        sendFieldEmail();
        if (!Test.isRunningTest() && !isAll) {
            Database.executeBatch(new RollupToMaintenanceContractBatch(), 1);
        }

    }
    @TestVisible
    private void sendFieldEmail() {
        PretechBatchEmailUtil be = new PretechBatchEmailUtil();
        String[] toList = new String[] {UserInfo.getUserEmail()};
        String title = '备品可视化更新修理失败';
        String[] ccList = new String[] {};
        if (System.Test.isRunningTest()) {
            be.successMail('', 1);
        }
        if (failedCount > 0) {
            be.failedMail(toList, ccList, title,
                          String.join(this.emailMessages, '\n'),
                          totalCount, totalCount - failedCount, failedCount, '', false);
            be.send();
        }
    }
}