global class setOrderShareBatch implements Database.Batchable<sObject>, Database.Stateful {
    // public String query;
    
    public List<String> accountIdList;
    public Boolean sharedFlag = false;
    public Integer total = 0;
    public Map<String,String> accountIdMap = new Map<String,String>(); 
    public Integer accounttotal = 0;
    global setOrderShareBatch() {

    }
    global setOrderShareBatch(Boolean sharedFlag) {
        this.sharedFlag = sharedFlag;
    }

    global setOrderShareBatch(List<String> accountIdList) {
        this.accountIdList = accountIdList;
    }

    global Database.QueryLocator start(Database.BatchableContext bc) {

        if (accountIdList != null && accountIdList.size() > 0) {
            return Database.getQueryLocator([SELECT Id,OwnerId,Owner.IsActive,AccountId FROM  order WHERE AccountId IN:accountIdList order by createdDate ]);    
        } else if (sharedFlag) {
            return Database.getQueryLocator([SELECT Id,OwnerId,Owner.IsActive,AccountId FROM  order WHERE SharedFlag__c = true order by createdDate ]);  
        } else {
            return Database.getQueryLocator([SELECT Id,OwnerId,Owner.IsActive,AccountId FROM  order order by createdDate ]);  
        }
        
    }

    global void execute(Database.BatchableContext BC, List<Order> orderList) {

        // 获取合同上客户名Id 
        Set<Id> accountIdSet = new Set<Id>();
        for(Order order:orderList){
            String accountId = order.AccountId;
            if (!accountIdMap.containsKey(accountId)) {
                accountIdSet.add(order.AccountId);
                accountIdMap.put(accountId,accountId);    
            }
            accounttotal++;
            
        }

        // 1.根据客户Id，查找关联的所有合同
        List<Order> getOrderList = [SELECT Id,OwnerId,Owner.IsActive,AccountId 
                                        FROM  order 
                                        WHERE AccountId IN:accountIdSet ORDER BY AccountId];
        // 客户Id 合同所有人Id 合同所有人对应的全部合同Id集合
        Map<Id,Map<Id,List<Id>>> accountId_orderOwnerId_orderIdMap = new Map<Id,Map<Id,List<Id>>>();
        for (Order order:getOrderList ) {
            String accountId = order.AccountId;
            
            // 合同所有人 他名下的合同Id集合
            Map<Id,List<Id>> orderOwnerId_orderIdMap = new Map<Id,List<Id>>();
            if (accountId_orderOwnerId_orderIdMap.containsKey(accountId)) {
                orderOwnerId_orderIdMap = accountId_orderOwnerId_orderIdMap.get(accountId);
            }

            List<Id> orderIdList = new List<Id>();
            String orderOwnerId = order.OwnerId;
            if (orderOwnerId_orderIdMap.containsKey(orderOwnerId)) {
                orderIdList = orderOwnerId_orderIdMap.get(orderOwnerId);
            }
            orderIdList.add(order.Id);

 
            orderOwnerId_orderIdMap.put(orderOwnerId, orderIdList);
            // 客户下 合同所有人与合同Id
            accountId_orderOwnerId_orderIdMap.put(accountId, orderOwnerId_orderIdMap);
            
        }
        // 根据客户Id，查找客户下 客户团队用户 
        List<AccountTeamMember> accountTeamMemberList = new List<AccountTeamMember>();
        accountTeamMemberList = [SELECT Id, AccountId, UserId, user.IsActive  
                                    FROM AccountTeamMember 
                                    WHERE user.IsActive = true 
                                        AND AccountId IN:accountIdSet ORDER BY AccountId];

        // 排除 合同所有人后 将合同共享给有效的用户
        if (accountTeamMemberList.size() > 0) {

            Map<String,OrderShare> orderShareMap = new Map<String,OrderShare>();
            for (AccountTeamMember atm:accountTeamMemberList ) {
                // 
                String accountId = atm.AccountId;
                String userId = atm.UserId;
                if (accountId_orderOwnerId_orderIdMap.containsKey(accountId)) {
                    Map<Id,List<Id>> orderOwnerId_orderIdMap = accountId_orderOwnerId_orderIdMap.get(accountId);

                    for (Id orderOwnerId : orderOwnerId_orderIdMap.keySet()) {
                        
                        if (userId != orderOwnerId) {
                            for (Id orderId:orderOwnerId_orderIdMap.get(orderOwnerId) ) {
                                String kv =  orderId+'_' +userId;
                                OrderShare aos = new OrderShare(
                                    RowCause = 'Manual',
                                    orderId = orderId,
                                    UserOrGroupId = userId,
                                    OrderAccessLevel = 'Edit');
                                orderShareMap.put(kv, aos);
                            }
                        }
                    }
                }
            }

            Savepoint sp = Database.setSavepoint();
            try {
                if (orderShareMap.size() > 0) {
                    insert orderShareMap.values();
                }  
                if(Test.isRunningTest()){
                    Integer num = Integer.valueOf('TestError');
                }
            } catch (Exception ex) {
                Database.rollback(sp);
                BatchIF_Log__c iflog = new BatchIF_Log__c();
                iflog.Type__c = 'OrderShare';
                String datetimeStr = String.valueOf(Datetime.now()).replace('-','').replace(' ','').replace(':','');
                iflog.MessageGroupNumber__c = datetimeStr;
                iflog.Log__c = 'Account Id \n';
                for (Id accountId :accountIdSet ) {
                    iflog.Log__c += accountId +',\n';
                }
                
                iflog.ErrorLog__c = '';
                insert iflog;
            }
            total += orderShareMap.size();
           
        }
        try {
            update orderList;

            if(Test.isRunningTest()){
                Integer num = Integer.valueOf('TestError');
            }
        } catch (Exception ex) {

                BatchIF_Log__c iflog = new BatchIF_Log__c();
                iflog.Type__c = 'OrderShare';
                String datetimeStr = String.valueOf(Datetime.now()).replace('-','').replace(' ','').replace(':','');
                iflog.MessageGroupNumber__c = datetimeStr;
                iflog.Log__c = 'Order Id \n';
                for (order orderId :orderList ) {
                    iflog.Log__c += orderId +',\n';
                }
                
                iflog.ErrorLog__c = '';
                insert iflog;
            }
    }

    global void finish(Database.BatchableContext BC) {
        System.debug('accountIdMap--->'+accountIdMap);
        System.debug('total--->'+total);

        BatchIF_Log__c iflog = new BatchIF_Log__c();
        iflog.Type__c = 'OrderShare';
        String datetimeStr = String.valueOf(Datetime.now()).replace('-','').replace(' ','').replace(':','');
        iflog.MessageGroupNumber__c = datetimeStr;
        iflog.Log__c = 'Account Count \n';
        iflog.Log__c += accountIdMap.size() +'\n';
        iflog.Log__c += 'OrderShare Count \n';
        iflog.Log__c += total +'\n';
        iflog.ErrorLog__c = '';
        insert iflog;
    }
}