public with sharing class SetProductTargetBatch implements Database.Batchable<sObject> {

    String query;
    //  现在年度
    private Integer currentYear;

    // 既存目标数据
    private Map<String, Opportunity> oppsMap;
    private Map<String, Key_Product_Goals__c> keysMap;
    private Map<String, AggregateResult> oliMap;

    // 目标区分
    // public String target_category;
    private RecordType rt; 

    private Map<String, List<Double>> proportion;    // 比重

    //public static List<String> amountCategory;
    public static List<ImportantProductCategory__c> pcList;
    public static Map<String, boolean> isCntMap = new Map<String, boolean>();

    // 初始化,查询赋值 pcList
    static {
        pcList = [select depName__c,importantProductGoaIName__c,commodityCode__c,commodityName__c,if_Quantity__c,sort__c from ImportantProductCategory__c order by sort__c];
        for (ImportantProductCategory__c pc : pcList) {
            isCntMap.put(pc.importantProductGoaIName__c + '_' + pc.depName__c, pc.if_Quantity__c);
        }
    }

    // 重点产品API名图
    private static Map<String, String> impProductApiMap = SetProductTargetController.impProductApiMap;
    /**
     * 构造器,初始化
     */
    public SetProductTargetBatch(){
    }

    /**
     * 开始方法
     */
    public Database.QueryLocator start(Database.BatchableContext BC) {
        // 查询中间表,获取当前 年 的信息  key__c 剪切, 第二数据是数字字段名
        query = 'select key__c,SAP_Province__c,iYear__c,Owner_System__c,Department__c,Num_Of_OPD__c,Target_Source__c from Key_Product_Goals__c where Is_Processing__c = true';
        // iYear__c = \'' + iYear + '
        return Database.getQueryLocator(query);
    }

    /**
     * 执行方法,添加保存
     */

    public void execute(Database.BatchableContext BC, List<Key_Product_Goals__c> Key_Product_Goals) { 
        system.debug('SetProductTargetBatch开始。');
        init(Key_Product_Goals);
        system.debug('oppsMap ++++' + oppsMap.size() + oppsMap);
        system.debug('Key_Product_Goals.size()');
        system.debug(Key_Product_Goals.size());

        List<Opportunity> insertList = new List<Opportunity>();
        List<Opportunity> updateList = new List<Opportunity>();
        List<Opportunity> deleteList = new List<Opportunity>();

        // 将 查询出来的 中间表数据,赋值为 FALSE
        List<Key_Product_Goals__c> klist = new List<Key_Product_Goals__c>();

        // Savepoint sp = Database.setSavepoint();
        
        Map<String, Decimal> oppAmount = new Map<String, Decimal>();
        Map<String,String> saveAmountCategoryMap = new Map<String,String>();
        for (Key_Product_Goals__c Key_Product_Goal: Key_Product_Goals) {
            String key = Key_Product_Goal.key__c;
            list<string> user_Id_target_category = key.split('_');
            if(user_Id_target_category.size() < 5){
                return;
            }
            Key_Product_Goal.Is_Processing__c = false;
            // string user_Id = user_Id_target_category[0];
            string target_category = user_Id_target_category[1];
            string importantProductGoaIName = user_Id_target_category[2];
            string depName = user_Id_target_category[3];
            String target_Source = user_Id_target_category[4];
            // 一年分成12条数据 
            for (Integer i = 0; i < 12; i++) {
                Integer y = Integer.valueOf(Key_Product_Goal.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);
                // 按金额分类顺序处理
                // 数据检索Key
                String tem_key = key + '_' + sTagetDay;

                system.debug('tem_key++++++ ' + tem_key);
                Opportunity newopp = new Opportunity();
                // 每月数据赋值
                if (oppsMap.containskey(tem_key)) {
                    newopp = oppsMap.get(tem_key);
                    if (Key_Product_Goal.Num_Of_OPD__c == null || Key_Product_Goal.Num_Of_OPD__c == 0) {
                        deleteList.add(newopp);
                        continue;
                    }
                    newopp.OwnerId = Key_Product_Goal.Owner_System__c;
                    newopp.Owner_System__c = Key_Product_Goal.Owner_System__c;
                    String tem_depName = (depName == null || depName == '') ? 'GI' : depName;
                    newopp.Proportion__c = proportion.get(tem_depName)[i];
                    newopp.Num_Of_OPD__c = Key_Product_Goal.Num_Of_OPD__c;
                    oppAmount.put(newopp.Id, Key_Product_Goal.Num_Of_OPD__c);

                    system.debug('待更新');
                    updateList.add(newopp);

                    if (!saveAmountCategoryMap.containskey(importantProductGoaIName + '_' + depName)) {
                        saveAmountCategoryMap.put(importantProductGoaIName + '_' + depName, 
                                                  importantProductGoaIName + '_' + depName);
                    }
                } else {
                    if (Key_Product_Goal.Num_Of_OPD__c == null || Key_Product_Goal.Num_Of_OPD__c == 0) {
                        continue;
                    }
                    newopp.Name = Key_Product_Goal.SAP_Province__c + ' ' + importantProductGoaIName;

                    newopp.StageName = '目標';
                    newopp.OwnerId = Key_Product_Goal.Owner_System__c;
                    // トリガをスルーのため、ここでやります
                    newopp.Owner_System__c = Key_Product_Goal.Owner_System__c;

                    newopp.Opportunity_Category__c = depName;
                    String tem_depName = (depName == null || depName == '') ? 'GI' : depName;
                    newopp.Proportion__c = proportion.get(tem_depName)[i];
                    newopp.CloseDate = tagetDay;
                    newopp.Num_Of_OPD__c = Key_Product_Goal.Num_Of_OPD__c;
                    newopp.Target_category__c = target_category;
                    newopp.Important_Key_product_category__c = importantProductGoaIName;
                    newopp.SAP_Province__c = Key_Product_Goal.SAP_Province__c;
                    newopp.RecordTypeId = rt.Id;
                    newopp.OCM_Target_period__c = String.valueOf(integer.valueOf(Key_Product_Goal.iYear__c) - 1867 + 'P');
                    newopp.Target_Source__c = target_Source;

                    insertList.add(newopp);
                    if (!saveAmountCategoryMap.containskey(importantProductGoaIName + '_' + depName)) {
                        saveAmountCategoryMap.put(importantProductGoaIName + '_' + depName, importantProductGoaIName + '_' + depName);
                    }
                }
            }
        }
        // トリガをスルー
        StaticParameter.EscapeOpportunityBefUpdTrigger = true;
        StaticParameter.EscapeOpportunityHpDeptUpdTrigger = true;
        StaticParameter.EscapeSyncOpportunityTrigger = true;
        StaticParameter.EscapeNFM001Trigger = true;
        StaticParameter.EscapeNFM001AgencyContractTrigger = true;
        StaticParameter.EscapeNFM007Trigger = true;

        // 更新数据库
        if (insertList.size() > 0) {

            // 添加数据
            insert insertList;
            // 添加自定义日志
            // bLog.Log3__c = '添加完成\n';
            // update bLog;
            
            Map<String,PricebookEntry> pricebookEntryMap = new Map<String,PricebookEntry>();
            // 搜索产品
            for (ImportantProductCategory__c pc : pcList){
                String dep = pc.depName__c;
                Map<String, String> impmap = getImpProductMap(dep);
                String soql = 'select Id from PricebookEntry' + 
                              ' where IsActive = true ' + 
                              '   and Product2.' + impProductApiMap.get(pc.importantProductGoaIName__c) + ' = true';
                if (dep != null && dep.length() > 0) {
                      soql += '   and Product2.' + impmap.get(pc.importantProductGoaIName__c) + ' = true';
                }
                      soql += '   and CurrencyIsoCode = \'CNY\' limit 1';
                System.debug('zheli000:'+soql);
                
                List<PricebookEntry> pbes = Database.query(soql);
                if (pbes.size() < 1) {
                    return;
                }
                system.debug('zheli001:'+pc+'~'+pbes[0]);
                pricebookEntryMap.put(pc.importantProductGoaIName__c + '_' + pc.depName__c, pbes[0]);  
            }
            system.debug('zheli002:'+insertList+'~'+isCntMap);
            // 商談新規後、商談商品作成
            List<OpportunityLineItem> oli = new List<OpportunityLineItem>();
            for (Opportunity insOpp : [select Id, Amount,Num_Of_OPD__c,Important_Key_product_category__c,Opportunity_Category__c,Objective__c from Opportunity where Id in :insertList]) {
                oli.add(new OpportunityLineItem(
                    OpportunityId = insOpp.Id,
                    PricebookEntryId = pricebookEntryMap.get(insOpp.Important_Key_product_category__c + '_' + insOpp.Opportunity_Category__c).Id,
                    Quantity = isCntMap.get(insOpp.Important_Key_product_category__c + '_' + insOpp.Opportunity_Category__c) == false ? 1 : insOpp.Num_Of_OPD__c,
                    UnitPrice = isCntMap.get(insOpp.Important_Key_product_category__c + '_' + insOpp.Opportunity_Category__c) == false ? insOpp.Num_Of_OPD__c : 0
                ));
            }

            // oli 插入数据 询价产品
            system.debug('zheli003:'+oli);
            insert oli; 
            // 添加自定义数据
            // bLog.Log3__c += 'oli 插入完成';
            // update bLog;
        }
        
        if (updateList.size() > 0) {


            // 更新 询价
            update updateList; 
            // bLog.Log2__c = '更新完成\n';
            // update bLog;
            
            List<OpportunityLineItem> oli = new List<OpportunityLineItem>();
            for (OpportunityLineItem updOli : [select Id, OpportunityId, Opportunity.Important_Key_product_category__c, Opportunity.Opportunity_Category__c from OpportunityLineItem where OpportunityId in : updateList]) {
                updOli.UnitPrice = isCntMap.get(updOli.Opportunity.Important_Key_product_category__c + '_' + updOli.Opportunity.Opportunity_Category__c) == false ? oppAmount.get(updOli.OpportunityId) : 0;
                updOli.Quantity = isCntMap.get(updOli.Opportunity.Important_Key_product_category__c + '_' + updOli.Opportunity.Opportunity_Category__c) == false ? 1 : oppAmount.get(updOli.OpportunityId);
                oli.add(updOli);
            }
            
            // 更新 oli 询价产品
            update oli;
            
            // 添加自定义数据
            // bLog.Log2__c += 'oli 更新完成';
            // update bLog;
        }
        
        if (deleteList.size() > 0) {system.debug('=====saveLogic-5');delete deleteList;}
        upsert Key_Product_Goals;
    }

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

    private Map<String, String> getImpProductMap(String ac) {
        Map<String, String> impmap = new Map<String, String> {
                '重点产品01' => 'Important_Rroduct_1' + ac +'__c',
                '重点产品02' => 'Important_Rroduct_2' + ac +'__c',
                '重点产品03' => 'Important_Rroduct_3' + ac +'__c',
                '重点产品04' => 'Important_Rroduct_4' + ac +'__c',
                '重点产品05' => 'Important_Rroduct_5' + ac +'__c',
                '重点产品06' => 'Important_Rroduct_6' + ac +'__c',
                '重点产品07' => 'Important_Rroduct_7' + ac +'__c',
                '重点产品08' => 'Important_Rroduct_8' + ac +'__c',
                '重点产品09' => 'Important_Rroduct_9' + ac +'__c',
                '重点产品10' => 'Important_Rroduct_10' + ac +'__c',
                '重点产品11' => 'Important_Rroduct_11' + ac +'__c',
                '重点产品12' => 'Important_Rroduct_12' + ac +'__c',
                '重点产品13' => 'Important_Rroduct_13' + ac +'__c',
                '重点产品14' => 'Important_Rroduct_14' + ac +'__c',
                '重点产品15' => 'Important_Rroduct_15' + ac +'__c',
                '重点产品16' => 'Important_Rroduct_16' + ac +'__c',
                '重点产品17' => 'Important_Rroduct_17' + ac +'__c',
                '重点产品18' => 'Important_Rroduct_18' + ac +'__c',
                '重点产品19' => 'Important_Rroduct_19' + ac +'__c',
                '重点产品20' => 'Important_Rroduct_20' + ac +'__c',
                '重点产品21' => 'Important_Rroduct_21' + ac +'__c',
                '重点产品22' => 'Important_Rroduct_22' + ac +'__c',
                '重点产品23' => 'Important_Rroduct_23' + ac +'__c',
                '重点产品24' => 'Important_Rroduct_24' + ac +'__c',
                '重点产品25' => 'Important_Rroduct_25' + ac +'__c',
                '重点产品26' => 'Important_Rroduct_26' + ac +'__c',
                '重点产品27' => 'Important_Rroduct_27' + ac +'__c',
                '重点产品28' => 'Important_Rroduct_28' + ac +'__c',
                '重点产品29' => 'Important_Rroduct_29' + ac +'__c',
                '重点产品30' => 'Important_Rroduct_30' + ac +'__c',
                '重点产品31' => 'Important_Rroduct_31' + ac +'__c'
        };
        return impmap;
    }

    private void init(List<Key_Product_Goals__c> Key_Product_Goals){
        system.debug('init 11111');
        // 每月比重
        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);
        }

        //初始化既存目标数据
        oppsMap = new Map<String, Opportunity>();
        oliMap = new Map<String, AggregateResult>();
        string target_category = '省重点产品目标';

        // 获取目标数据类型
        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;
        //WLIG-BZVDB4 20210414  ljh update start
        //string currentPeriod = String.valueOf(year - 1867 + 'P');
        list<string> currentPeriods = new list<string>();
        string currentPeriod = String.valueOf(year - 1867 + 'P');
        currentPeriods.add(currentPeriod);
        currentPeriod = String.valueOf(year + 1 - 1867 + 'P');
        currentPeriods.add(currentPeriod);
        currentPeriod = String.valueOf(year - 1 - 1867 + 'P');
        currentPeriods.add(currentPeriod);
        //WLIG-BZVDB4 20210414  ljh update end
        
        system.debug('init 22222');
        // 获取 省 用于搜索所对应询价
        list<String> provinces = new list<String>();
        // 获取 目标分类 用于搜索所对应询价
        List<String> target_Sources = new List<String>();
        for (Key_Product_Goals__c Key_Product : Key_Product_Goals) {
            string key = Key_Product.key__c;
            list<string> user_Id_target_category = key.split('_');
            if (user_Id_target_category.size() < 4) {
                //Database.rollback(sp);
                return;
            }
            Key_Product.Is_Processing__c = false;
            string user_Id = user_Id_target_category[0];
            provinces.add(user_Id);
            target_Sources.add(Key_Product.Target_Source__c);

        }
        //获取既存Opportunity
        Opportunity[] opportunitys = [select
                        Id, OwnerId, Opportunity_Category__c, Proportion__c, CloseDate,
                        Amount, Objective__c, Target_category__c, Important_Key_product_category__c,
                        SAP_Province__c, RecordTypeId, OCM_Target_period__c, Owner_System__c,
                        Target_Source__c
                 from Opportunity
                where Target_category__c = :target_category
                  and RecordTypeId = :rt.Id
                  //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
                  and SAP_Province__c in :provinces
                  and Target_Source__c in :target_Sources];
        system.debug('init 33333' + 'target_category' + target_category + 'currentPeriod' + currentPeriod +  'provinces' + provinces + 'target_Source' + target_Sources);
        system.debug('既存Opportunitys:'+opportunitys);
        if(opportunitys.size() <= 0)
            return;

        for (Opportunity opp : opportunitys) {
            if (opp.OwnerId != null && opp.CloseDate !=null){
                //数据检索key
                String key = opp.SAP_Province__c + '_' + opp.Target_category__c + '_' + opp.Important_Key_product_category__c
                           + '_' + opp.Opportunity_Category__c + '_' + opp.Target_Source__c + '_' + String.valueOf(opp.CloseDate);
                system.debug('=======key'+key);
                oppsMap.put(key, opp);
            }
        }
        // 获取既存商品作成
        AggregateResult[] opportunityLineItems = [select OpportunityId,SUM(NumberOfObjective__c) sum_n,SUM(Objective__c) sum_o from OpportunityLineItem where OpportunityId in :opportunitys group by OpportunityId];
        oliMap = new Map<String, AggregateResult>();
        for (AggregateResult oli : opportunityLineItems) {
            oliMap.put((String) oli.get('OpportunityId'), oli);
        }
    }

}