// RowDataを残すため、@future execute にします
global class NFM012WebService {
    // Integer batchsize = 200;  考量する必要がないと思います。
    global class Deposit {
        webservice NFMUtil.Monitoring Monitoring;
        webservice NFM012WebService.GeneralData[] GeneralData;
    }
    global class GeneralData {
        webservice String EndUserNo;				// DealerNumber
        webservice String UpdateDate;				// 更新日期
        webservice Decimal DepositAmount;			// 结余金额
    }

    // 非同期を見せかけ、常にreturn void
    webservice static void NFM012(NFM012WebService.Deposit Deposit) {
        if (Deposit == null) {
            return;
        }
        NFMUtil.Monitoring Monitoring = Deposit.Monitoring;
        if (Monitoring == null) {
            return;
        }
        BatchIF_Log__c rowData = NFMUtil.saveRowData(Monitoring, 'NFM012', Deposit.GeneralData);
        System.debug('rowData123456:' + rowData);
        if (String.isBlank(rowData.Log__c) == false) executefuture(rowData.Id);
	}

    @future
    global static void executefuture(String rowData_Id) {
        execute(rowData_Id);
    }
    global static void execute(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 = 'NFM012';
        iflog.MessageGroupNumber__c = rowData.MessageGroupNumber__c;
        iflog.Log__c = logstr;
        iflog.ErrorLog__c = '';
        insert iflog;

        String rowDataStr = NFMUtil.getRowDataStr(rowData);
        List<GeneralData> generalDataList = (List<GeneralData>) JSON.deserialize(rowDataStr, List<GeneralData>.class);
        if (generalDataList == null || generalDataList.size() == 0) {
            return;
        }

        Savepoint sp = Database.setSavepoint();
        try {
            // 更新対応配列をセット
            List<Account> accList = new List<Account>();
            Map<String, Account> accUpdateMap = new Map<String, Account>();
            for (NFM012WebService.GeneralData GeneralData : generalDataList) {
                if (GeneralData.EndUserNo == null || GeneralData.EndUserNo == '') {
                    // 必須項目がない場合、処理と飛ばす
                    iflog.ErrorLog__c += 'EndUserNo is required\n';
                    continue;
                }

                // 項目転送のセット
                Account acc = new Account();
                acc.AgentCode_Ext__c = GeneralData.EndUserNo;
                if (accUpdateMap.get(acc.AgentCode_Ext__c) == null) {
                    accList.add(acc);
                    accUpdateMap.put(acc.AgentCode_Ext__c, acc);
                    logstr += GeneralData.EndUserNo + ' ';
                } else {
                    acc = accUpdateMap.get(acc.AgentCode_Ext__c);
                }
                acc.Deposit_Receipt_Completion_Day__c   = NFMUtil.parseStr2Date(GeneralData.UpdateDate);
                acc.Deposit_Receipt_Finished__c         = GeneralData.DepositAmount;
            }
            if (accList.size() > 0) {
                Database.UpsertResult[] srList = Database.upsert(accList, Account.Fields.AgentCode_Ext__c, false);
                // Iterate through each returned result
                for (Integer i = 0; i < srList.size(); i++) {
                    Account acc = accList[i];
                    Database.UpsertResult sr = srList[i];
                    if (sr.isSuccess()) {
                        // Operation was successful, so get the ID of the record that was processed
                        System.debug('Successfully inserted account. Account ID: ' + sr.getId());
                    }
                    else {
                        // Operation failed, so get all errors
                        for(Database.Error err : sr.getErrors()) {
                            //System.debug(err.getStatusCode() + ': ' + err.getMessage());
                            iflog.ErrorLog__c += acc.AgentCode_Ext__c + ', ' + err.getStatusCode() + ': ' + err.getMessage() + '\n';
                        }
                    }
                }
            }
            logstr += '\nend';
            rowData.retry_cnt__c=0;
        } catch(Exception ex) {
            // エラーが発生した場合
            Database.rollback(sp);
            System.debug(Logginglevel.ERROR, 'NFM012_' + rowData.MessageGroupNumber__c + ':' + ex.getMessage());
            System.debug(Logginglevel.ERROR, 'NFM012_' + 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+'错误次数已经超过自动收信设定的最大次数，请手动收信';
            }
        }
        update rowData;
        iflog.Log__c = logstr;
        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;
    }
}