global class SetPersonalProductTargetBatch implements Database.Batchable<sObject> {
    
    String query;
    // 目标的数据类型 
    private RecordType rt;
    //  现在年度
    private Integer currentYear;
    // 比重
    private Map<String, List<Double>> proportion;
    // 既存目标数据
    private Map<String, Opportunity> oppsMap;
    private Map<Id,OpportunityLineItem> oliMap;
    
    private static Map<String, String> impProductApiMap = SetPersonalProductTargetController.impProductApiMap;
        
        /* new Map<String, String> {
        '重点产品01' => 'Important_product1__c',
        '重点产品02' => 'Important_product2__c',
        '重点产品03' => 'Important_product3__c',
        '重点产品04' => 'Important_product4__c',
        '重点产品05' => 'Important_product5__c',
        '重点产品06' => 'Important_product6__c',
        '重点产品07' => 'Important_product7__c',
        '重点产品08' => 'Important_product8__c',
        '重点产品09' => 'Important_product9__c',
        '重点产品10' => 'Important_product10__c',
        '重点产品11' => 'Important_product11__c',
        '重点产品12' => 'Important_product12__c',
        '重点产品13' => 'Important_product13__c',
        '重点产品14' => 'Important_product14__c',
        '重点产品15' => 'Important_product15__c',
        '重点产品16' => 'Important_product16__c',
        '重点产品17' => 'Important_product17__c',
        '重点产品18' => 'Important_product18__c',
        '重点产品19' => 'Important_product19__c',
        '重点产品20' => 'Important_product20__c',
        '重点产品21' => 'Important_product21__c',
        '重点产品22' => 'Important_product22__c',
        '重点产品23' => 'Important_product23__c',
        '重点产品24' => 'Important_product24__c',
        '重点产品25' => 'Important_product25__c',
        '重点产品26' => 'Important_product26__c',
        '重点产品27' => 'Important_product27__c',
        '重点产品28' => 'Important_product28__c',
        '重点产品29' => 'Important_product29__c',
        '重点产品30' => 'Important_product30__c'
        //'重点产品31' => 'Important_product31__c'
   };
        */
    // xiongyl--start
    public static List<ImportantProductCategory__c> pcList;
    public static Map<String, boolean> isCntMap = new Map<String, boolean>();
    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);
        }
    }
    
    global SetPersonalProductTargetBatch() {
    }
    
    global Database.QueryLocator start(Database.BatchableContext BC) {
        query = 'select key__c,Num_Of_OPD__c,user_Alias__c,SAP_Province__c,Is_Processing__c,iYear__c from Num_Major_Product__c where Is_Processing__c = true';
        return Database.getQueryLocator(query);
    }
    
    global void execute(Database.BatchableContext BC, List<Num_Major_Product__c> Num_Major_Products) {
        system.debug('SetPersonalProductTargetBatch开始。');
        init(Num_Major_Products);
        List<Opportunity> insertList = new List<Opportunity>();
        List<Opportunity> updateList = new List<Opportunity>();
        List<Opportunity> deleteList = new List<Opportunity>();

        /*Savepoint sp = Database.setSavepoint();
        try {*/
            Map<String, Decimal> oppAmount = new Map<String, Decimal>();
            Map<String,String> saveAmountCategoryMap = new Map<String,String>();
            for (Num_Major_Product__c Num_Major_Product : Num_Major_Products){
                string key = Num_Major_Product.key__c;
                list<string> user_Id_target_category = key.split('_');
                if(user_Id_target_category.size() < 4){
                    //Database.rollback(sp);
                    return;
                }
                Num_Major_Product.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];
                for (Integer i = 0; i < 12; i++) {
                    Integer y = Integer.valueOf(Num_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);
                    string tem_key = key + '_' + sTagetDay;
                    // 每月数据赋值
                    Opportunity newopp = new Opportunity();
                    //
                    if (oppsMap.containskey(tem_key)) {
                        system.debug('------------test flag');
                        newopp = oppsMap.get(tem_key);
                        if (Num_Major_Product.Num_Of_OPD__c == null || Num_Major_Product.Num_Of_OPD__c == 0) {
                            deleteList.add(newopp);
                            continue;
                        }
                        newopp.OwnerId = user_Id;
                        newopp.Owner_System__c = user_Id;
                        newopp.Num_Of_OPD__c = Num_Major_Product.Num_Of_OPD__c;
                        String tem_depName = (depName == null || depName == '') ? 'GI' : depName;
                        newopp.Proportion__c = proportion.get(tem_depName)[i];
                        oppAmount.put(newopp.Id, Num_Major_Product.Num_Of_OPD__c);
                        updateList.add(newopp);
                        
                        if (!saveAmountCategoryMap.containskey(importantProductGoaIName + '_' + depName)) {
                            saveAmountCategoryMap.put(importantProductGoaIName + '_' + depName, 
                                                      importantProductGoaIName + '_' + depName);
                        }
                    }else {
                        system.debug('------------tem_key:'+tem_key);
                        if (Num_Major_Product.Num_Of_OPD__c == null || Num_Major_Product.Num_Of_OPD__c == 0) {
                            continue;
                        }
                        newopp = new Opportunity();
                        newopp.Name = Num_Major_Product.user_Alias__c + ' ' + importantProductGoaIName ;
                        newopp.StageName = '目標';
                        newopp.OwnerId = user_Id;
                        // トリガをスルーのため、ここでやります
                        newopp.Owner_System__c = user_Id;
                        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 = Num_Major_Product.Num_Of_OPD__c;
                        newopp.Target_category__c = target_category;
                        newopp.Important_Key_product_category__c = importantProductGoaIName;
                        newopp.SAP_Province__c = Num_Major_Product.SAP_Province__c;
                        newopp.RecordTypeId = rt.Id;
                        newopp.OCM_Target_period__c = String.valueOf(integer.valueOf(Num_Major_Product.iYear__c) - 1867 + 'P');
                        newopp.CurrencyIsoCode = 'CNY';
                        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;
                system.debug('=====saveLogic-3');
                Map<String,PricebookEntry> pricebookEntryMap = new Map<String,PricebookEntry>();
                // 製品を検索
                for (ImportantProductCategory__c pc : pcList){                   
                    String dep = pc.depName__c;
                    Map<String, String> impmap = getImpProductMap(dep);                  
                    // TODO GI BFなどの判別は要らない？
                    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(soql);
                    
                    List<PricebookEntry> pbes = Database.query(soql);
                    if (pbes.size() < 1) {
                        //Database.rollback(sp);
                        return;
                    }
                    pricebookEntryMap.put(pc.importantProductGoaIName__c + '_' + pc.depName__c, pbes[0]);
                }
                // 商談新規後、商談商品作成
                List<OpportunityLineItem> oli = new List<OpportunityLineItem>();
                for (Opportunity insOpp : [select Id,Important_Key_product_category__c,Opportunity_Category__c,Amount,Num_Of_OPD__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
                    ));
                }
                insert oli;
            }
            
            system.debug('updateList:'+updateList);
            if (updateList.size() > 0) {
                upsert updateList;
                system.debug('=====saveLogic-4');
                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);
                }
                update oli;
            }
            
            if (deleteList.size() > 0) {system.debug('=====saveLogic-5');delete deleteList;}
            upsert Num_Major_Products;
       /* }catch (Exception e) {
            system.debug('=====saveLogic-e' + e.getMessage());
            //ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.INFO, e.getMessage()));
            Database.rollback(sp);
        }*/
    }
    
    global void finish(Database.BatchableContext BC) {
        system.debug('SetPersonalProductTargetBatch结束.');
        Database.executeBatch(new SetPersonalTargetBatch(), 10);
    }
    
    private void init(List<Num_Major_Product__c> Num_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);
        }
       
        
        //初始化既存目标数据
        oppsMap = new Map<String, Opportunity>();
        oliMap = new Map<Id,OpportunityLineItem>();
        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;
        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);
        //SWAG-BB48QB 判断当前时间是否是4月15日之后 start
        currentPeriod = String.valueOf(year - 1 - 1867 + 'P');
        currentPeriods.add(currentPeriod);
        //SWAG-BB48QB 判断当前时间是否是4月15日之后 end

        // 获取 存储用户 用于搜索所对应询价
        list<ID> OwnerId = new list<ID>();
        for (Num_Major_Product__c Num_Major_Product : Num_Major_Products) {
            string key = Num_Major_Product.key__c;
            list<string> user_Id_target_category = key.split('_');
            if (user_Id_target_category.size() < 4) {
                //Database.rollback(sp);
                return;
            }
            Num_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, Important_Key_product_category__c,
                        SAP_Province__c, RecordTypeId, OCM_Target_period__c, Owner_System__c
                 from Opportunity
                where Target_category__c = :target_category
                  and RecordTypeId = :rt.Id
                  and OwnerId in : OwnerId
                  and OCM_Target_period__c in :currentPeriods];
        system.debug('既存Opportunitys:'+opportunitys);
        if(opportunitys.size() <= 0)
            return;

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

    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 List<User> getUserList() {
        String soql = 'select Id, Salesdepartment__c, Province__c, Alias, Job_Category__c, Product_specialist_incharge_dept__c,'
                    + ' ProfileId, Profile.Name, UserRoleId, UserRole.Name, Sales_Speciality__c, Post__c'
                    + ' from User where IsActive = true and Test_staff__c = false and UserType = \'Standard\' ';
        return Database.query(soql);
    }*/


}