global class SetPersonalTargetBatch implements Database.Batchable<sObject> {
    String query;
    // 目标的数据类型 
    private RecordType rt;
    //  现在年度
    private Integer currentYear;
    // 比重
    private Map<String, List<Double>> proportion;
    // 既存目标数据
    private Map<String, Opportunity> oppMap;
    private Map<Id, OpportunityLineItem> oliMap;
    private static String[] amountCategory = new String[] {'GI','ET','BF','GS','URO','GYN','ENT','ENG'};

    //  当前年度
    private Integer iYear;
    //  当前月份
    private Integer iMonth;
    //  当前日期
    private Integer iDay;
    //  4月可编辑期限
    private Integer iBuffer;

    // 当前期
    public String currentPeriod { get; private set; }
    global SetPersonalTargetBatch() {
    }

    global Database.QueryLocator start(Database.BatchableContext BC) {
        query = 'select key__c,Amount__c,user_Alias__c,SAP_Province__c,Is_Processing__c,iYear__c,Use_Start_Date__c from Amount_Major_Product__c where Is_Processing__c = true';
        return Database.getQueryLocator(query);
    }
    global void execute(Database.BatchableContext BC, List<Amount_Major_Product__c> Amount_Major_Products) {
        init(Amount_Major_Products);
        List<Opportunity> saveList = new List<Opportunity>();
        List<Opportunity> deleteList = new List<Opportunity>();

        for (Amount_Major_Product__c Amount_Major_Product : Amount_Major_Products){
            string key = Amount_Major_Product.key__c;
            list<string> user_Id_target_category = key.split('_');
            if(user_Id_target_category.size() < 2){
                return;
            }
            Amount_Major_Product.Is_Processing__c = false;
            string user_Id = user_Id_target_category[0];
            string target_category = user_Id_target_category[1];
            //使用开始后目标金额补正系数计算
            //Decimal proportionSum = 0.0;
            Map<String, Decimal> proportionSumMap = new Map<String, Decimal>();
            for (Integer j = 0; j < amountCategory.size(); j++) {
                String amountC = amountCategory[j];
                proportionSumMap.put(amountC, 0.0);
            }
            for (Integer i = 0; i < 12; i++) {
                Integer y = Integer.valueOf(Amount_Major_Product.iYear__c);
                Integer m = 4 + i;
                if (m > 12) {
                    y += 1;
                    m -= 12;
                }
                String syear = String.valueOf(y);
                String smonth = String.valueOf(m);
                if (m < 10) {
                    smonth = '0' + smonth;
                }
                String sTagetDay = syear + '-' + smonth + '-01';
                Date tagetDay = Date.valueOf(sTagetDay);
                if (Amount_Major_Product.Use_Start_Date__c < tagetDay) {
                    //proportionSum += proportion.get(amountC)[i];
                    for (Integer j = 0; j < amountCategory.size(); j++) {
                        String amountC = amountCategory[j];
                        proportionSumMap.put(amountC, proportionSumMap.get(amountC) + proportion.get(amountC)[i]);
                    }
                }
            }
            //proportionSum = proportionSum / 100;
            for (Integer j = 0; j < amountCategory.size(); j++) {
                String amountC = amountCategory[j];
                proportionSumMap.put(amountC, proportionSumMap.get(amountC) / 100);
            }
            //--------------
            for (Integer i = 0; i < 12; i++) {
                Integer y = Integer.valueOf(Amount_Major_Product.iYear__c);
                Integer m = 4 + i;
                if (m > 12) {
                    y += 1;
                    m -= 12;
                }
                String syear = String.valueOf(y);
                String smonth = String.valueOf(m);
                if (m < 10) {
                    smonth = '0' + smonth;
                }
                String sTagetDay = syear + '-' + smonth + '-01';
                Date tagetDay = Date.valueOf(sTagetDay);
                if (Amount_Major_Product.Use_Start_Date__c >= tagetDay) {
                    // 使用開始当月 及び 開始前 は目標を登録しない，无视。
                    continue;
                }
                String temp_key = user_Id + '_' + target_category+'_' +sTagetDay;
                // 每月数据赋值
                Opportunity opp = new Opportunity();
                System.debug('temp_key===' + temp_key+';==='+oppMap.keySet());
                System.debug('===真/假===' + oppMap.containskey(temp_key));
                if (oppMap.containskey(temp_key)) {
                    opp = oppMap.get(temp_key);
                    if (Amount_Major_Product.Amount__c == null || Amount_Major_Product.Amount__c == 0 ) {
                        deleteList.add(opp);
                        continue;
                    }
                    
                    opp.Name = Amount_Major_Product.user_Alias__c + ' 担当目标';
                    opp.StageName = '目標';
                    opp.OwnerId = user_Id;
                    // トリガをスルーのため、ここでやります
                    opp.Owner_System__c = user_Id;
                    opp.Opportunity_Category__c = target_category;
                    opp.Proportion__c = proportion.get(target_category)[i];
                    opp.CloseDate = tagetDay;
                    opp.Amount = Amount_Major_Product.Amount__c / proportionSumMap.get(target_category);
                    opp.Target_category__c = '担当目标';
                    opp.SAP_Province__c = Amount_Major_Product.SAP_Province__c;
                    opp.RecordTypeId = rt.Id;
                    opp.OCM_Target_period__c = String.valueOf(integer.valueOf(Amount_Major_Product.iYear__c) - 1867 + 'P');
                    opp.CurrencyIsoCode = 'CNY';
                    saveList.add(opp);
                } else {
                    if (Amount_Major_Product.Amount__c == null || Amount_Major_Product.Amount__c == 0) {
                        continue;
                    }
                    opp.Name = Amount_Major_Product.user_Alias__c + ' 担当目标';
                    opp.StageName = '目標';
                    opp.OwnerId = user_Id;
                    // トリガをスルーのため、ここでやります
                    opp.Owner_System__c = user_Id;
                    opp.Opportunity_Category__c = target_category;
                    opp.Proportion__c = proportion.get(target_category)[i];
                    opp.CloseDate = tagetDay;
                    opp.Amount = Amount_Major_Product.Amount__c / proportionSumMap.get(target_category);
                    opp.Target_category__c = '担当目标';
                    opp.SAP_Province__c = Amount_Major_Product.SAP_Province__c;
                    opp.RecordTypeId = rt.Id;
                    opp.OCM_Target_period__c = String.valueOf(integer.valueOf(Amount_Major_Product.iYear__c) - 1867 + 'P');
                    opp.CurrencyIsoCode = 'CNY';
                    // 加入保存列表
                    saveList.add(opp);
                }
                
            }
        }
        System.debug('deleteList+++++++++++' + deleteList.size());
        // トリガをスルー
        StaticParameter.EscapeOpportunityBefUpdTrigger = true;
        StaticParameter.EscapeOpportunityHpDeptUpdTrigger = true;
        StaticParameter.EscapeNFM007Trigger = true;

        if (deleteList.size() > 0) {
            delete deleteList;
        }

        if (saveList.size() > 0) {
            System.debug('saveList+++++++++++' + saveList[0]);
            upsert saveList;
        }
        
        
        upsert Amount_Major_Products;

    }

    global void finish(Database.BatchableContext BC) {
        system.debug('SetPersonalTargetBatch结束.');
    }

    private void init(List<Amount_Major_Product__c> Amount_Major_Products){
        // 每月比重
        if (proportion == null) {
            proportion = new Map<String, List<Double>>();
            String strObjectiveProportionGI = System.Label.ObjectiveProportionGI;
            List<String> objectiveProportionGI = strObjectiveProportionGI.split(',');
            List<Double> doubleGI = new List<Double>();
            for (String strGI : objectiveProportionGI) {
                doubleGI.add(Double.valueOf(strGI));
            }
            proportion.put('GI', doubleGI);

            String strObjectiveProportionET = System.Label.ObjectiveProportionET;
            List<String> objectiveProportionET = strObjectiveProportionET.split(',');
            List<Double> doubleET = new List<Double>();
            for (String strET : objectiveProportionET) {
                doubleET.add(Double.valueOf(strET));
            }
            proportion.put('ET', doubleET);

            String strObjectiveProportionBF = System.Label.ObjectiveProportionBF;
            List<String> objectiveProportionBF = strObjectiveProportionBF.split(',');
            List<Double> doubleBF = new List<Double>();
            for (String strBF : objectiveProportionBF) {
                doubleBF.add(Double.valueOf(strBF));
            }
            proportion.put('BF', doubleBF);

            String strObjectiveProportionGS = System.Label.ObjectiveProportionGS;
            List<String> objectiveProportionGS = strObjectiveProportionGS.split(',');
            List<Double> doubleGS = new List<Double>();
            for (String strGS : objectiveProportionGS) {
                doubleGS.add(Double.valueOf(strGS));
            }
            proportion.put('GS', doubleGS);

            String strObjectiveProportionURO = System.Label.ObjectiveProportionURO;
            List<String> objectiveProportionURO = strObjectiveProportionURO.split(',');
            List<Double> doubleURO = new List<Double>();
            for (String strURO : objectiveProportionURO) {
                doubleURO.add(Double.valueOf(strURO));
            }
            proportion.put('URO', doubleURO);

            String strObjectiveProportionGYN = System.Label.ObjectiveProportionGYN;
            List<String> objectiveProportionGYN = strObjectiveProportionGYN.split(',');
            List<Double> doubleGYN = new List<Double>();
            for (String strGYN : objectiveProportionGYN) {
                doubleGYN.add(Double.valueOf(strGYN));
            }
            proportion.put('GYN', doubleGYN);

            String strObjectiveProportionENT = System.Label.ObjectiveProportionENT;
            List<String> objectiveProportionENT = strObjectiveProportionENT.split(',');
            List<Double> doubleENT = new List<Double>();
            for (String strENT : objectiveProportionENT) {
                doubleENT.add(Double.valueOf(strENT));
            }
            proportion.put('ENT', doubleENT);

            String strObjectiveProportionOTH = System.Label.ObjectiveProportionOTH;
            List<String> objectiveProportionOTH = strObjectiveProportionOTH.split(',');
            List<Double> doubleOTH = new List<Double>();
            for (String strOTH : objectiveProportionOTH) {
                doubleOTH.add(Double.valueOf(strOTH));
            }
            proportion.put('OTH', doubleOTH);

            String strObjectiveProportionENG = System.Label.ObjectiveProportionENG;
            List<String> objectiveProportionENG = strObjectiveProportionENG.split(',');
            List<Double> doubleENG = new List<Double>();
            for (String strENG : objectiveProportionENG) {
                doubleENG.add(Double.valueOf(strENG));
            }
            proportion.put('ENG', doubleENG);
        }
        //初始化既存目标数据
        oppMap = new Map<String, Opportunity>();
        // 目标的数据类型
        if (rt == null) {
            rt = [select Id from RecordType where SobjectType = 'Opportunity' and IsActive = true and DeveloperName = 'Target'];
        }
        // 现在时间
        Date dateNow = Date.today();
        Integer year = dateNow.year();
        Integer month = dateNow.month();
        if (month < 4) {
            year -= 1;
        }
        // 初始化
        currentYear = year;
        iYear = year;
        iMonth = month;
        iDay = dateNow.day();
        iBuffer = Integer.valueOf(System.Label.SetPersonalTarget_buffer_day);
        
        //WLIG-BZVDB4 20210414  ljh update start
        //currentPeriod = String.valueOf(iYear - 1867 + 'P');
        list<string> currentPeriods = new list<string>();
        currentPeriod = String.valueOf(iYear - 1867 + 'P');
        currentPeriods.add(currentPeriod);
        currentPeriod = String.valueOf(iYear + 1 - 1867 + 'P');
        currentPeriods.add(currentPeriod);
        currentPeriod = String.valueOf(iYear - 1 - 1867 + 'P');
        currentPeriods.add(currentPeriod);
        //WLIG-BZVDB4 20210414  ljh update end
        //--------------
        // 获取 存储用户 用于搜索所对应询价
        list<ID> OwnerId = new list<ID>();
        for (Amount_Major_Product__c Amount_Major_Product : Amount_Major_Products) {
            string key = Amount_Major_Product.key__c;
            list<string> user_Id_target_category = key.split('_');
            if (user_Id_target_category.size() < 2) {
                //Database.rollback(sp);
                return;
            }
            Amount_Major_Product.Is_Processing__c = false;
            string user_Id = user_Id_target_category[0];
            OwnerId.add(user_Id);
        }      
        //获取既存Opportunity
        Opportunity[] opportunitys = [select
                        Id, OwnerId, Opportunity_Category__c, Proportion__c, CloseDate,
                        Amount, Objective__c, Target_category__c,
                        SAP_Province__c, RecordTypeId, OCM_Target_period__c
                 from Opportunity
                where Target_category__c = '担当目标'
                  and RecordTypeId = :rt.Id
                  and OwnerId in :OwnerId
                  //WLIG-BZVDB4 20210414  ljh update start
                  //and OCM_Target_period__c = :currentPeriod];
                  and OCM_Target_period__c in :currentPeriods];
                  //WLIG-BZVDB4 20210414  ljh update end
        system.debug('currentPeriod:'+currentPeriod);
        if(opportunitys.size() <= 0)
            return;

        for (Opportunity opp : opportunitys) {
            if (opp.OwnerId != null && opp.CloseDate !=null){
                //数据检索key
                String key = opp.OwnerId + '_' + opp.Opportunity_Category__c+'_'+String.valueOf(opp.CloseDate);
                //system.debug('===key'+key);
                oppMap.put(key, opp);
            }
        }
        //
    }
}