public with sharing class AssetPowerBIBatch implements Database.Batchable<SObject> {
    public static Integer FIELDMAX = 200;
    private final List<Id> TEST_ID = null;
    private final Date createDate = null;
    private BatchIF_Log__c iflog;
    private static final Integer MAXERRORCNT = 20; // 邮件表单位最大错误信息显示数量
    private static final Boolean ALLORNONE = false; // 全部保存

    //--------------------------------------------------------------------------------------------------------------------------
    public AssetPowerBIBatch() {
        iflog = new BatchIF_Log__c();
        iflog.Type__c = 'PushNotification';
        iflog.Log__c  = '备品备份：AssetPowerBIBatch start\n';
        insert iflog;
    }
    public AssetPowerBIBatch(List<Id> testId) {
        TEST_ID = testId;
        iflog = new BatchIF_Log__c();
        iflog.Type__c = 'PushNotification';
        iflog.Log__c  = '备品备份：AssetPowerBIBatch start\n';
        insert iflog;
    }
    public AssetPowerBIBatch(List<Id> testId, Date createDate) {
        TEST_ID = testId;
        this.createDate = createDate;
        iflog = new BatchIF_Log__c();
        iflog.Type__c = 'PushNotification';
        iflog.Log__c  = '备品备份：AssetPowerBIBatch start\n';
        insert iflog;
    }
     public AssetPowerBIBatch( Date createDate) {
        this.createDate = createDate;
        iflog = new BatchIF_Log__c();
        iflog.Type__c = 'PushNotification';
        iflog.Log__c  = '备品备份：AssetPowerBIBatch start\n';
        insert iflog;
    }
    //---------------------------------------------------------------------------------------------------------------------------
    public static String makeSql(SS_Batch_Column_Mapping__c setting, Set<String> apiTempSet) {
        for (Integer i = 1; i <= FIELDMAX; i++) {
            String fromColumn = 'From_Column_' + ('00' + i).right(3) + '__c';
            String apiStr = String.valueOf(setting.get(fromColumn));
            if (String.isBlank(apiStr) == false && apiTempSet.contains(apiStr) == false) {
                apiTempSet.add(apiStr);
            }
        }
        system.debug('apiTempSet' + apiTempSet);
        String soql = 'Select ' + String.join(new List<String>(apiTempSet), ',') + ' from ' + setting.Name;
        system.debug('soql' + soql);
        return soql;
    }
    //---------------------------------------------------------------------------------------------------------------------------
    public static Object getValue(SObject sobj, String field) {
        List<String> fieldPathList = field.split('\\.');
        Object rtn = null;
        for (Integer i = 0; i < fieldPathList.size(); i++) {
            String fieldPath = fieldPathList[i];
            if (i == fieldPathList.size() - 1) {
                rtn = sobj.get(fieldPath);
            } else {
                sobj = sobj.getSObject(fieldPath);
                if (sobj == null) {
                    break;
                }
            }
        }
        return rtn;
    }
    //-------------------------------------------------------------------------------------------------------------------------
    public Database.QueryLocator start(Database.BatchableContext BC) {
        SS_Batch_Column_Mapping__c oppMapping = SS_Batch_Column_Mapping__c.getValues('asset');//asset
        Set<String> apiTempSet = new Set<String>();
        String soql = makeSql(oppMapping, apiTempSet);
        soql += ' where recordType.DeveloperName  = \'Shipment\' ';

        // 2020/07/08 taoqz add start 
        // 备品用途附属品=false
        // 备品中心确认=TRUE
        
        List<String> fixtureStatus = new List<String>();
        fixtureStatus.add('待废弃');
        fixtureStatus.add('待移至报废区');
        fixtureStatus.add('丢失');
        fixtureStatus.add('废弃');
            
        if (!Test.isRunningTest() && TEST_ID == null) {
            soql += ' and Loaner_accsessary__c = false and AssetManageConfirm__c = true and Fixture_Status__c not in :fixtureStatus';
        }
        // 2020/07/08 taoqz add end

        if (TEST_ID <> null) {
            soql += ' and Id IN: TEST_ID';
        } 
        return Database.getQueryLocator(soql);
    }
    //-----------------------------------------------------------------------------------------------------------------
    public void execute(Database.BatchableContext BC, List<asset> apbList) {
        System.debug('apbList.size()'+apbList.size());
        try {

            list<BatchIF_Log__c> ifloglist = [select id , ErrorLog__c from BatchIF_Log__c where id = :  iflog.id];
            if (ifloglist.size() > 0 ) {
                iflog = ifloglist[0];
            }
            List<SObject> acList = new List<SObject>();
            SS_Batch_Column_Mapping__c assetMapping = SS_Batch_Column_Mapping__c.getValues('asset');
            Set<String> assetTempSet = new Set<String>();
            String assetSql = makeSql(assetMapping, assetTempSet);
            Schema.SObjectType assetType = Schema.getGlobalDescribe().get(String.valueOf(assetMapping.get('SS_TableName__c')));
            for (Asset oli : apbList) {
                SObject asObj = assetType.newSObject();
                for (Integer i = 1; i <= FIELDMAX; i++) {
                    String lpadI = ('00' + i).right(3);
                    String fromColumn = 'From_Column_' + lpadI + '__c';
                    String apiStr = String.valueOf(assetMapping.get(fromColumn));
                    if (String.isBlank(apiStr) == false) {
                        String ssColumn = 'SS_Column_' + lpadI + '__c';
                        String ssApiStr = String.valueOf(assetMapping.get(ssColumn));
                        asObj.put(ssApiStr, getValue(oli, apiStr));
                    }
                }
                asObj.put('createDate__c', Date.today());
                if (createDate != null) {
                    asObj.put('createDate__c', createDate);
                }
                acList.add(asObj);
            }
            String tmp = iflog.ErrorLog__c;
            if (iflog.ErrorLog__c == null) {
                tmp = '';
            }
            Database.SaveResult[] lsr5 = Database.insert(acList, false);
            list<ID> assetIdList = new list<ID>();

            for (SObject temAsset : acList) {
                if (temAsset.get('id') == null) {
                    assetIdList.add( (ID) temAsset.get('Id__c'));
                }
            }
            system.debug('lsr5:' + lsr5);
            for (Integer tIdx = 0; tIdx < lsr5.size(); tIdx++) {
                Database.SaveResult sr = lsr5[tIdx];
                if (!sr.isSuccess()) {
                    String message = '';
                    for (Database.Error err : sr.getErrors()) {
                        message = '\n\n 错误数据类型:Asset'
                                  + '\n 错误信息：'
                                  + err.getStatusCode() + ':'
                                  + err.getMessage();

                        break;
                    }
                    tmp += message;
                    if (!message.equals('')) {
                        break;
                    }
                }
            }
            if (assetIdList.size() > 0 ) {
                tmp += '\n 更新失败原数据ID:' + assetIdList;
            }
            if (tmp != null && tmp.length() > 65000) {
                tmp = tmp.substring(0, 65000);
                tmp += ' ...have more lines...';
            }
            iflog.ErrorLog__c = tmp;

            system.debug('tmp:' + tmp + '\n ErrorLog__c' + iflog.ErrorLog__c );
        } catch (Exception ex) {
            iflog.ErrorLog__c += ex;

        }
        update iflog;

    }

    //--------------------------------------------------------------------------------------------------------------------
    public void finish(Database.BatchableContext BC) {
        list<BatchIF_Log__c> ifloglist = [select id , ErrorLog__c, Log__c from BatchIF_Log__c where id = :  iflog.id];
        if (ifloglist.size() > 0 ) {
            iflog = ifloglist[0];
        }
        iflog.Log__c += '\n AssetPowerBIBatch end';
        String tmp = iflog.ErrorLog__c;
        if (tmp != null && tmp.length() > 65000) {
            tmp = tmp.substring(0, 65000);
            tmp += ' ...have more lines...';
            iflog.ErrorLog__c = tmp;
        }
        upsert iflog;
    }

    @TestVisible private void test() {
        Integer i = 0;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
    }

}