global class EquipmentSetDailyBatch implements Database.Batchable<sObject>, Database.Stateful {

    private static final Integer MAXERRORCNT = 20; // 邮件表单位最大错误信息显示数量
    private static final Boolean ALLORNONE = false; // 全部保存

    private ErrorBean eb = new ErrorBean(); // 邮件发送ERRORBEAN

    private Integer maxCount = 3;
    private Integer nowCount = 0;

    /*
    创建于20161126 by ZDF
        目的1：询价的「20.最终发货日」is null and 最新预定归还日 = 今天 then 最新预定归还日 + 30天（循环）
        目的2：IF 修理的「13.RC修理品返送日」 is null and 最新预定归还日 = 今天 then 最新预定归还日 + 30天。（循环）
    */
    id Rentalid;
    global EquipmentSetDailyBatch(id Rentalid) {
        this.Rentalid = Rentalid;
        Integer i = 0;
        
    }

    global Database.QueryLocator start(Database.BatchableContext BC) {
        String query;
        query = 'select id,name from Rental_Apply__c';
        if(Rentalid!=null){
            query = query + ' where id = \'' + Rentalid +'\'';
        } else {
            query = query + ' where Status__c != \'取消\'';
        }
        //query = '';
        return Database.getQueryLocator(query);
    }

    global void execute(Database.BatchableContext BC, List<Rental_Apply__c> RaList) {
        //************************************Create 20161126   黑名单设计 by ZDF************************************//
        //                                      Start
        //************************************Create 20161126   黑名单设计 by ZDF************************************//
        List<Rental_Apply_Equipment_Set__c> RaesList    =   new List<Rental_Apply_Equipment_Set__c>();
        List<Rental_Apply_Equipment_Set__c> RaesListForUpdate   =   new List<Rental_Apply_Equipment_Set__c>();
        RaesList    =   [select
                            id,
                            name,
                            Bollow_Date__c,
                            Rental_Apply__c,
                            Shippment_loaner_time2__c,
                            Loaner_received_time__c,
                            Received_Confirm__c,
                            Asset_return_time__c,
                            Rental_Apply__r.RC_Ordered_Date__c,
                            Rental_Apply__r.Demo_purpose1__c,
                            Rental_Apply__r.Demo_purpose2__c,
                            Rental_Apply__r.Follow_UP_Opp__c,
                            Rental_Apply__r.Follow_UP_Opp__r.Shipping_Finished_Day_Func__c,
                            Rental_Apply__r.Repair__c,
                            Rental_Apply__r.Repair__r.SAP_not_accept_repair_result__c,
                            Rental_Apply__r.Repair__r.Repair_Shipped_Date__c,
                            Rental_Apply__r.Repair__r.Status1__c,
                            Rental_Apply__r.next_action_Text__c,
                            Rental_Apply__r.QISRepair__c,
                            Rental_Apply__r.QIS_Repair_Shipped_Date__c,
                            Rental_Apply__r.QIS_ReplaceDeliveryDate__c,
                            Rental_Apply__r.QIS_Reply_day__c,
                            Rental_Apply__r.QIS_Cancel_Submit_day__c,
                            Rental_Apply__r.QIS_cancel_date__c,
                            Rental_Apply__r.Request_demo_day__c,
                            Final_reply_day__c,
                            Add_Day_For_RC__c
                        from
                            Rental_Apply_Equipment_Set__c
                        where
                            Rental_Apply__c in:RaList
                            ];
        for (Rental_Apply_Equipment_Set__c Raesc : RaesList) {
            if (Raesc.Rental_Apply__r.Follow_UP_Opp__c != null
                    && Raesc.Rental_Apply__r.Demo_purpose2__c == '已购待货') {
                if (Raesc.Rental_Apply__r.Follow_UP_Opp__r.Shipping_Finished_Day_Func__c == null
                        && Raesc.Final_reply_day__c == Date.today()) {
                    Raesc.Add_Day_For_RC__c = Raesc.Final_reply_day__c.addDays(30);
                } else if (Raesc.Rental_Apply__r.Follow_UP_Opp__r.Shipping_Finished_Day_Func__c != null) {
                    Raesc.Add_Day_For_RC__c = null;
                }
                RaesListForUpdate.Add(Raesc);
            }
            else if (Raesc.Rental_Apply__r.Repair__c != null
                    && (Raesc.Rental_Apply__r.Demo_purpose2__c == '一般用户'
                            || Raesc.Rental_Apply__r.Demo_purpose2__c == '故障排查'
                            || Raesc.Rental_Apply__r.Demo_purpose2__c == '保修用户'
                            || Raesc.Rental_Apply__r.Demo_purpose2__c == '市场多年保修'
                            || Raesc.Rental_Apply__r.Demo_purpose2__c == '再修理')
            ) {

                if (Raesc.Rental_Apply__r.Repair__r.Status1__c == '0.删除') {
                        //对于所有修理，如果修理状态变为删除时，申请单内最新预定归还日关联修理内‘不受理日(SAP)’+7天（自然日）
                        //if(Raesc.Rental_Apply__r.Repair__r.SAP_not_accept_repair_result__c != null ) {
                        //  Raesc.Add_Day_For_RC__c =   Raesc.Rental_Apply__r.Repair__r.SAP_not_accept_repair_result__c.addDays(7);
                        //  Raesc.Repair_Delete_Date__c = Raesc.Rental_Apply__r.Repair__r.SAP_not_accept_repair_result__c.addDays(7);
                        //}
                }
                else if (Raesc.Rental_Apply__r.Repair__r.Repair_Shipped_Date__c == null
                        &&  Raesc.Final_reply_day__c == Date.today()) {

                    if (Raesc.Rental_Apply__r.RC_Ordered_Date__c != null
                            && (Raesc.Rental_Apply__r.Demo_purpose2__c == '保修用户'
                                    || Raesc.Rental_Apply__r.Demo_purpose2__c == '市场多年保修')
                    ) {
                        //黑名单的1个月自动延期设置条件加一点：发货后7天后RC受理日不为空

                        Raesc.Add_Day_For_RC__c = Raesc.Final_reply_day__c.addDays(30);

                    }
                    else if (Raesc.Rental_Apply__r.Demo_purpose2__c == '一般用户') {

                        Raesc.Add_Day_For_RC__c = Raesc.Final_reply_day__c.addDays(30);

                    }
                    else if (Raesc.Rental_Apply__r.Demo_purpose2__c == '故障排查') {
                        //  到货NG一周内寄回 or 到货OK
                        if((Raesc.Received_Confirm__c == 'OK' || Raesc.Received_Confirm__c == '默认签收-OK')
                            || (Raesc.Received_Confirm__c == 'NG' && Raesc.Asset_return_time__c < Raesc.Loaner_received_time__c.addDays(7)) ) {
                            Raesc.Add_Day_For_RC__c = Raesc.Final_reply_day__c.addDays(30);
                        }
                    }
                    else if (Raesc.Rental_Apply__r.Demo_purpose2__c == '再修理') {

                        Raesc.Add_Day_For_RC__c = Raesc.Final_reply_day__c.addDays(30);

                    }
                    //Raesc.Add_Day_For_RC__c =   Raesc.Final_reply_day__c.addDays(30);
                }
                else if (Raesc.Rental_Apply__r.Repair__r.Repair_Shipped_Date__c != null) {

                    Raesc.Add_Day_For_RC__c = null;

                }

                RaesListForUpdate.Add(Raesc);

            }
            else if (Raesc.Rental_Apply__r.Demo_purpose2__c == '索赔QIS') {
                if (Raesc.Final_reply_day__c == Date.today()
                    && Raesc.Rental_Apply__r.Request_demo_day__c >= Date.newInstance(2019, 9, 1)
                    && (((Raesc.Rental_Apply__r.next_action_Text__c == '无偿维修'
                            || Raesc.Rental_Apply__r.next_action_Text__c == '无偿维修'
                            || Raesc.Rental_Apply__r.next_action_Text__c == '有偿维修'
                            || Raesc.Rental_Apply__r.next_action_Text__c == '有偿维修+无偿维修'
                        )
                            && (String.isNotBlank(Raesc.Rental_Apply__r.QISRepair__c)
                                    && Raesc.Rental_Apply__r.QIS_Repair_Shipped_Date__c == null
                                )
                        )
                        || (Raesc.Rental_Apply__r.next_action_Text__c == '无偿更换'
                                && Raesc.Rental_Apply__r.QIS_ReplaceDeliveryDate__c == null
                            )
                        || (Raesc.Rental_Apply__r.next_action_Text__c == '送回'
                                && Raesc.Rental_Apply__r.QIS_Reply_day__c == null
                            )
                        || (String.isBlank(Raesc.Rental_Apply__r.next_action_Text__c)
                                && Raesc.Rental_Apply__r.QIS_Cancel_Submit_day__c == null
                                && Raesc.Rental_Apply__r.QIS_cancel_date__c == null
                            )
                        )
                ) {
                    Raesc.Add_Day_For_RC__c = Raesc.Final_reply_day__c.addDays(30);
                    RaesListForUpdate.Add(Raesc);
                }
            }
        }
        if (RaesListForUpdate.size() > 0) {
            // update RaesListForUpdate;
            Database.SaveResult[] saveRes = Database.update(RaesListForUpdate, ALLORNONE);
            eb.setError(saveRes, MAXERRORCNT, Rental_Apply_Equipment_Set__c.sObjectType);
        }
        //************************************Create 20161126   黑名单设计 by ZDF************************************//
        //                                      END
        //************************************Create 20161126   黑名单设计 by ZDF************************************//
        //************************************Create 20170822   备品：7天默认签收的设置******************************//
        //                                      Start
        //************************************Create 20170822   备品：7天默认签收的设置******************************//
        RaesList    =   [select 
                            id,
                            name,
                            Shippment_loaner_time2__c,
                            Loaner_received_time__c,
                            RAES_Status__c,
                            Received_Confirm__c
                        from    
                            Rental_Apply_Equipment_Set__c
                        where   
                            Rental_Apply__c in:RaList
                            ];
        List<Rental_Apply_Equipment_Set__c> updateForDate = new List<Rental_Apply_Equipment_Set__c>();
        for (Rental_Apply_Equipment_Set__c Raesc : RaesList) {
            if (Raesc.Shippment_loaner_time2__c != null
                    && Raesc.Loaner_received_time__c == null
                    && Raesc.RAES_Status__c=='已出库') {
                if (Raesc.Shippment_loaner_time2__c <= system.now().addDays(-7)) {
                    Raesc.Loaner_received_time__c = system.now();
                    Raesc.Received_Confirm__c = '默认签收-OK';
                    updateForDate.add(Raesc);
                }
            }
        }
        if (updateForDate.size() > 0) {
            // update updateForDate;
            Database.SaveResult[] saveRes = Database.update(updateForDate, ALLORNONE);
            // 备品申请一览更新Error
            eb.setError(saveRes, MAXERRORCNT, Rental_Apply_Equipment_Set__c.sObjectType);
        }
        //************************************Create 20170822   备品：7天默认签收的设置******************************//
        //                                      End
        //************************************Create 20170822   备品：7天默认签收的设置******************************//
        //************************************Create 20170606   取消创建60天后未能分配的申请单***********************//
        //                                      Start
        //************************************Create 20170606   取消创建60天后未能分配的申请单***********************//
        // Datetime todayMin60Days = system.now().addDays(-60) ;
        // List<Rental_Apply__c> updateStatus = [  select id,isCanceled_TF__c,Status__c from Rental_Apply__c 
        //                                         where
        //                                             Request_approval_time__c <: todayMin60Days
        //                                         and
        //                                             Status__c = '已批准'
        //                                         and
        //                                             isCanceled_TF__c = false];
        // for(Rental_Apply__c ups : updateStatus){
        //     ups.Status__c = '取消';
        //     ups.isCanceled_TF__c = true;
        //     ups.Loaner_cancel_request__c ='本申请60天内无库存，关闭申请单';
        // }
        // IF(updateStatus.size()>0){
        //     update updateStatus;
        // }


        Datetime todayMin60Days = system.now().addDays(-60);
        List<Rental_Apply_Equipment_Set__c> updateStatus = [select id, Loaner_name_F__c, Fixture_Set__c,
                              Cancel_Reason__c, Loaner_cancel_Remarks__c
                         FROM Rental_Apply_Equipment_Set__c
                        WHERE Rental_Apply__c in:RaList
                        //2020/11/11   songxiaoqi  start 备品借出申请的OPD计划字段，如果是空，才可以自动取消
                          AND Rental_Apply__r.OPDPlan__c = null
                          //2020/11/11   songxiaoqi  end
                          AND Request_approval_time__c <: todayMin60Days
                          //已批准
                          AND (Rental_Apply__r.Status__c = :FixtureUtil.raStatusMap.get(FixtureUtil.RaStatus.Yi_Pi_Zhun.ordinal())
                                //已出库指示
                                OR Rental_Apply__r.Status__c = :FixtureUtil.raStatusMap.get(FixtureUtil.RaStatus.Yi_Chu_Ku_Zhi_Shi.ordinal()))
                          AND Yi_Assigned_Cnt__c = 0
                          AND Cancel_Select__c = false];
        Map<Id, String> raMap = new Map<Id, String>();
        Map<Id, Rental_Apply_Equipment_Set__c> oldRaesIdMap = new Map<Id, Rental_Apply_Equipment_Set__c>();
        for (Integer i = 0; i < updateStatus.size(); i ++) {
            Rental_Apply_Equipment_Set__c raes = updateStatus[i];
            raes.Cancel_Select__c = true;
            raes.Cancel_Reason__c = '被动取消';
            raes.Loaner_cancel_Remarks__c ='本一览60天内无库存，取消一览申请';
            // 古い一覧明細手動更新
            if (String.isBlank(raes.Fixture_Set__c)) {
                oldRaesIdMap.put(raes.Id, raes);
            }
            //关联地方 申请字段 isCanceled_TF_Set_Cnt
            if(!raMap.containsKey(raes.Rental_Apply__c)) {
                raMap.put(raes.Rental_Apply__c, '');
            }
            String str = raMap.get(raes.Rental_Apply__c);
            raMap.put(raes.Rental_Apply__c,str + '备品配套'
                    + (i + 1)
                    + ':<BR>'
                    // + '<a href="'
                    // + baseUrl + '/' + raes.Id
                    // +'">'
                    + '型号:' + raes.Loaner_name_F__c
                    // + '</a>'
                    + '<BR>');
        }
        List<Rental_Apply__c> raList2 = new List<Rental_Apply__c>();
        for (Id raId : raMap.keySet()) {
            raList2.add(new Rental_Apply__c(Id = raId, Email_Rental_Apply_Equipment_Set__c = raMap.get(raId)));
        }
        //先更新申请再更新一览，不然一览更新后发邮件时申请里面的字段会没有值
        if (!raList2.isEmpty()) {
            // update raList2;
            // 备品申请更新Error
            Database.SaveResult[] saveRes = Database.update(raList2, ALLORNONE);
            eb.setError(saveRes, MAXERRORCNT, Rental_Apply__c.sObjectType);
        }

        if (!updateStatus.isEmpty()) {
            // update updateStatus;
            Database.SaveResult[] saveRes = Database.update(updateStatus, ALLORNONE);
            // 备品申请一览更新Error
            eb.setError(saveRes, MAXERRORCNT, Rental_Apply_Equipment_Set__c.sObjectType);
        }

        // 古い一覧明細手動更新，一覧先に更新
        if (!oldRaesIdMap.isEmpty()) {
            Database.SaveResult[] saveRes = RentalApplyEquipmentSetHandler.recCancelNGDetailBatch(oldRaesIdMap, null);
            // 备品申请一览明细更新Error
            if (saveRes != null) {
                eb.setError(saveRes, MAXERRORCNT, Rental_Apply_Equipment_Set_Detail__c.sObjectType);
            }
        }

        //************************************Create 20170606   取消创建60天后未能分配的申请单***********************//
        //                                      End
        //************************************Create 20170606   取消创建60天后未能分配的申请单***********************//
    }

    global void finish(Database.BatchableContext BC) {
        Boolean haveError = false;
        String body = '';
        for (Id objId : eb.messageMap.keySet()) {
            haveError = true;
            body += eb.messageMap.get(objId) + '<br/>';
        }
        if (eb.overMax) {
            body += ':Over ' + MAXERRORCNT + 'Record<br/>';
        }
        if (haveError == true) {
            String batchUserId = System.Label.Batch_User_Id;
            List<User> us = [Select Id,NAme,Email From User Where Id =: batchUserId];
            if (!us.isEmpty()) {
                User use = us[0];
                if (String.isNotBlank(use.Email)) {
                    List<String> MailCc;
                    if (System.Label.Batch_Error_Send_To_CC != 'null') {
                        MailCc = System.Label.Batch_Error_Send_To_CC.split(',');
                    }
                    FixtureUtil.sendMessage(batchUserId,
                                            MailCc,
                                            'EquipmentSetDailyBatch Error',
                                             body
                                            );
                }
            }
            if (nowCount < maxCount) {
                EquipmentSetDailyBatch b = new EquipmentSetDailyBatch(this.Rentalid);
                b.nowCount = this.nowCount + 1;
                Database.executeBatch(b, 20);
            }
        }
    }


/************************* Inner Class ******************************/
    public class ErrorBean{
        // public String objectName;
        // public String objectLabel;
        public Map<Id, String> messageMap;
        public Boolean overMax;
        // public ErrorBean(Schema.sObjectType obj) {
        //     objectName = obj.getDescribe().getName();
        //     objectLabel = obj.getDescribe().getLabel();
        //     messageMap = new Map<Id, String>();
        //     overMax = false;
        // }
        public ErrorBean() {
          messageMap = new Map<Id, String>();
          overMax = false;
        }
        public void setError (Database.SaveResult[] saveRes, Integer maxCut, Schema.sObjectType obj) {
            if (messageMap.keySet().size() <= maxCut && overMax == false) {
                String objectName = obj.getDescribe().getName();
                String objectLabel = obj.getDescribe().getLabel();
                for (Database.SaveResult saveRe : saveRes) {
                    if (!saveRe.isSuccess()) {
                        if (!messageMap.containsKey(saveRe.getId())) {
                            if (messageMap.keySet().size() >= maxCut) {
                                overMax = true;
                                break;
                            }
                            for (Database.Error err : saveRe.getErrors()) {

                                String message = objectName + ':'
                                               + objectLabel + ':'
                                               + err.getStatusCode() + ':'
                                               + err.getFields() + ':'
                                               + err.getMessage();
                                messageMap.put(saveRe.getId(), message);
                                // 数据里面有复数错误信息的话只获取第一条
                                break;
                            }
                        }
                    }
                }
            }
        }
    }
}