/**
 * 计划外OPD计划，根据OPD计划排序进行排序
 * */
global class RentalAutomaticSortBeforeBatch implements Database.Batchable<sObject>,Database.Stateful {
    private final List<String> sdcName = null;
    public Date myStartDate;
    public Date myEndDate;
    // 2024-01-24 ssm 增加一个判断，在月末倒数第二个工作日的时候执行上月排序拷贝操作 start
    private Boolean executeCopyToBefore = false;
    // 2024-01-24 ssm 增加一个判断，在月末倒数第二个工作日的时候执行上月排序拷贝操作 end
    global RentalAutomaticSortBeforeBatch(){
    }

    // 2024-01-24 ssm 增加一个判断，在月末倒数第二个工作日的时候执行上月排序拷贝操作 start
    global RentalAutomaticSortBeforeBatch(Boolean exe){
        this.executeCopyToBefore = exe;
    }
    // 2024-01-24 ssm 增加一个判断，在月末倒数第二个工作日的时候执行上月排序拷贝操作 end

    global Database.QueryLocator start(Database.BatchableContext BC){
        String sql = 'SELECT Id,Name,type__c FROM opp2AuxiliarySort__c ';
        sql += ' WHERE Id != null ';
        if(sdcName <> null){
            sql += 'AND Name IN :sdcName ';
        }
        sql += ' AND (type__c = 2 OR type__c = 11)';
        sql += ' ORDER BY type__c';
        System.debug('=sql='+sql);
        return Database.getQueryLocator(sql);
    }

    global void execute(Database.BatchableContext BC, List<opp2AuxiliarySort__c> opp2AuxiliarySortList) {
		Date today = Date.today();
		// 获取从次月14日至再次月13日的日期
		Date startDate = today.addMonths(1).toStartOfMonth().addDays(13);
		Date endDate = today.addMonths(2).toStartOfMonth().addDays(12);
		Map<String,OPDPlan__c> opdAgainMap = New Map<String,OPDPlan__c>();
		// 先判断是否有计划外的OPD计划需要计算排队Num
		List<Rental_Apply__c> existSelectList = [
				SELECT Id
				FROM Rental_Apply__c
				WHERE OPDPlan__r.OPDLendSort__c != null
				  AND User_Salesdept__c =: opp2AuxiliarySortList[0].Name
				  AND OPDPlan__r.OPDPlan_ImplementDate__c >=: startDate
				  AND OPDPlan__r.OPDPlan_ImplementDate__c <=: endDate
				  AND OPDPlan__r.If_AutoSort__c = 0 
				  AND OPDPlan__r.RentalApplyNum__c = null
				  AND RA_Status__c IN ('草案中','申请中','已批准')];

		if (!existSelectList.isEmpty()) {
			// 如果存在，则整个计划外的OPD顺序都需要重新计算
			List<Rental_Apply__c> applyAgainSelectList = [
					SELECT Id,
						CreatedDate,
						User_Salesdept__c,//销售本部
						demo_purpose2__c,
						OPDPlan__r.RentalApplyNum__c,
						OPDPlan__r.OPDLendSort__c,
						Request_approval_time__c,
						Request_shipping_day__c
					FROM Rental_Apply__c
					WHERE OPDPlan__r.OPDLendSort__c != null
					  AND User_Salesdept__c =: opp2AuxiliarySortList[0].Name
					  AND OPDPlan__r.OPDPlan_ImplementDate__c >=: startDate
					  AND OPDPlan__r.OPDPlan_ImplementDate__c <=: endDate
					  AND OPDPlan__r.If_AutoSort__c = 0 
					  AND RA_Status__c IN ('草案中','申请中','已批准')
					ORDER BY demo_purpose2__c,
						OPDPlan__r.OPDLendSort__c ASC,
						Request_shipping_day__c ASC,
						Request_approval_time__c ASC];

			// 取计划内OPD最大的排队Num
			List<Rental_Apply__c> maxRentalApplyNum = [
					SELECT OPDPlan__r.RentalApplyNum__c
					FROM Rental_Apply__c
					WHERE OPDPlan__r.OPDLendSort__c != null
					  AND User_Salesdept__c =: opp2AuxiliarySortList[0].Name
					  AND OPDPlan__r.OPDPlan_ImplementDate__c >=: startDate
					  AND OPDPlan__r.OPDPlan_ImplementDate__c <=: endDate
					  AND OPDPlan__r.If_AutoSort__c = 1 
					ORDER BY OPDPlan__r.RentalApplyNum__c DESC LIMIT 1];

			Integer startNum = 0;
			if (!maxRentalApplyNum.isEmpty() && maxRentalApplyNum[0].OPDPlan__r.RentalApplyNum__c != null) {
				startNum = Integer.valueOf(maxRentalApplyNum[0].OPDPlan__r.RentalApplyNum__c);
			}

			List<RentalApplyComparator> sortableList = new List<RentalApplyComparator>();
			if(applyAgainSelectList.size() > 0){
				for (Rental_Apply__c obj : applyAgainSelectList) {
					sortableList.add(new RentalApplyComparator(obj));
				}

				sortableList.sort();

				List<Rental_Apply__c> sortedList = new List<Rental_Apply__c>();
				for (RentalApplyComparator comparator : sortableList) {
					sortedList.add(comparator.customRen);
				}

				Map<String,Integer> renApplyAgainMap = new Map<String,Integer>();
				for(Rental_Apply__c renApplyBefore : sortedList){
					// 计划外的OPD排队Num，从计划内最大的OPD排序Num开始排序
					renApplyAgainMap.put(renApplyBefore.User_Salesdept__c, startNum);
				}

				for (Rental_Apply__c renApplyAgain : sortedList) {
					String saleSdept = renApplyAgain.User_Salesdept__c;
					OPDPlan__c opd = new OPDPlan__c();
					if(renApplyAgainMap.containsKey(saleSdept) && !opdAgainMap.containsKey(renApplyAgain.OPDPlan__c)){
						opd.Id = renApplyAgain.OPDPlan__c;
						opd.RentalApplyNum__c = renApplyAgainMap.get(saleSdept) + 1;
						Integer numOPDPlan = Integer.valueOf(renApplyAgainMap.get(saleSdept) + 1);
						renApplyAgainMap.put(saleSdept, numOPDPlan);
						opdAgainMap.put(opd.Id, opd);
					}
				}
			}

			if (opdAgainMap != null && opdAgainMap.size() > 0) {
				update opdAgainMap.values();
			}
		}
    }

    global void finish(Database.BatchableContext BC) {
        // 2024-01-24 ssm 增加一个判断，在月末倒数第二个工作日的时候执行上月排序拷贝操作 start
        if (this.executeCopyToBefore) {
            Id execBTId = Database.executebatch(new OPDLendSortCopyToSortBeforeBatch(), 100);
        }
        // 2024-01-24 ssm 增加一个判断，在月末倒数第二个工作日的时候执行上月排序拷贝操作 end
    }

    public class RentalApplyComparator implements Comparable {
    public Rental_Apply__c customRen;

        public RentalApplyComparator(Rental_Apply__c obj) {
            this.customRen = obj;
        }

        public Integer compareTo(Object renToCompare) {
            RentalApplyComparator compareToRen = (RentalApplyComparator)renToCompare;

            // 根据使用目的进行排序
            Integer returnValue = comparePurposeOrder(compareToRen.customRen.demo_purpose2__c, customRen.demo_purpose2__c);
            if (returnValue != 0) {
                return returnValue;
            }

            // 如果使用目的相同，按照OPD排序
            if (customRen.OPDPlan__r.OPDLendSort__c < compareToRen.customRen.OPDPlan__r.OPDLendSort__c) {
                returnValue = -1;
            } else if (customRen.OPDPlan__r.OPDLendSort__c > compareToRen.customRen.OPDPlan__r.OPDLendSort__c) {
                returnValue = 1;
            }
            if (returnValue != 0) {
                return returnValue;
            }

            if(customRen.demo_purpose2__c == '学会展会' && compareToRen.customRen.demo_purpose2__c == '学会展会'){
                // 如果OPD相同，按照希望到货日排序
                if (customRen.Request_shipping_day__c < compareToRen.customRen.Request_shipping_day__c) {
                    returnValue = -1;
                } else if (customRen.Request_shipping_day__c > compareToRen.customRen.Request_shipping_day__c) {
                    returnValue = 1;
                }
                if (returnValue != 0) {
                    return returnValue;
                }
            }

            // 如果希望到货日相同，按照批准日期排序
            if (customRen.Request_approval_time__c < compareToRen.customRen.Request_approval_time__c) {
                returnValue = -1;
            } else if (customRen.Request_approval_time__c > compareToRen.customRen.Request_approval_time__c){
                returnValue = 1;
            } 

            if (returnValue != 0) {
                return returnValue;
            }
            
            // 按照创建时间排序
            if (customRen.CreatedDate < compareToRen.customRen.CreatedDate) {
                returnValue = -1;
            } else if (customRen.CreatedDate > compareToRen.customRen.CreatedDate) {
                returnValue = 1;
            }
            if (returnValue != 0) {
                return returnValue;
            }
            return returnValue;
        }

        private Integer comparePurposeOrder(String purpose1, String purpose2) {
            // 定义使用目的的排序顺序
            Map<String, Integer> purposeOrderMap = new Map<String, Integer>{
                '学会展会' => 1,
                '已购待货' => 2,
                '新产品评价' => 3,
                '试用（有询价）' => 4,
                '试用（无询价）' => 4
            };

            // 获取使用目的的排序顺序
            Integer order1 = purposeOrderMap.containsKey(purpose1) ? purposeOrderMap.get(purpose1) : 5;
            Integer order2 = purposeOrderMap.containsKey(purpose2) ? purposeOrderMap.get(purpose2) : 5;
            // 如果使用目的不在定义的排序顺序内，默认按照字母顺序排序

            Integer returnValue = 0;
            if (order1 < order2) {
                returnValue = 1;
            } else if (order2 > order1){
                returnValue = -1;
            }
            return returnValue;
        }
    }
}