/*
* @author 李　逸飛
* @date 2018.11.6
* @related OLY_OCM-473
* A Batch for generate/update Product_CategoryPrice_Table
*/
global without sharing class ET_Product_CategoryPrice_Table_Batch implements Database.Batchable<sObject>, Database.Stateful{

    global Integer totalCount = 0; // 总件数
    global Integer executedCount = 0;
    global Integer successCount = 0; // 成功件数
    global Integer failedCount = 0;  // 失败件数
    global String errMsgBody = ''; // 错误信息汇总
    // global Boolean isAllFlag = false;


    global Database.QueryLocator start(Database.BatchableContext BC){
        System.debug('********** ET_Product_CategoryPrice_Table_Batch ' + BC.getJobId() + 'start');
        Date systemDate = Date.today();
        systemDate = systemDate.addDays(-Integer.valueof(System.Label.ET_Date_Calculate));
        Set<String> s = new Set<String>{'停止','有効','有効（再申請中）','失効（期限内生産済在庫対応）'};

        Product2 p = [SELECT Plan_Term__c FROM Product2
            WHERE Is_ET_APP__c = TRUE
            AND Category3__c <> ''
            AND SFDA_Status__c IN :s
            LIMIT 1];
        String term = p.Plan_Term__c.left(4);

        /*
         *  按财年代码筛选本次 Batch 产生/更新的行
         */
        Product_CategoryPrice_Table__c [] pcts = [
                SELECT Id
                FROM  Product_CategoryPrice_Table__c
                WHERE OCM_Term__c = :term
        ];
        /*
         *  清除表中临时统计信息
         */
        for(Product_CategoryPrice_Table__c  pct: pcts) {
            pct.put('Product_Amount__c',0);
            pct.put('Product_Total_Price__c',0);
        }
        update pcts;
        /*
         *  构造 SOQL 查询，
         *  从产品表获取 {
         *      Plan_Term__c: 计画财年
         *      Category3__c: 第三分类
         *      Intra_Trade_List_RMB__c: 内贸定价(RMB)
         *  }
         *  字段
         */

        String query = 'SELECT Id, Intra_Trade_List_RMB__c, Asset_Model_No__c,' +
                        ' Category3__c, Category4__c, Plan_Term__c' +
                        ' FROM Product2' +
                        ' where Is_ET_APP__c = true ';
        // if (true != this.isAllFlag) {
        //        query += ' and LastModifiedDate >= :systemDate ';
        // }
               query += ' and Category3__c <> \'\' ' +
                        ' and SFDA_Status__c in :s';
        return Database.getQueryLocator(query);
    }

    global void execute(Database.BatchableContext BC, List<Product2> productList){
        totalCount += productList.size();

        Map<String,List<Product2>> uniKeyToPDListMap = new Map<String,List<Product2>>();
        System.debug('ET_Product_CategoryPrice_Table_Batch execute start');
        /*
         *   参照项目 ‘OLY财年’ 说明，财年应取产品计划财年前三码+'P'
         *   产品分类价格表项的 UniqueKey 以 计画财年:第三分类:第4分类 记入;
         *   以此 UniqueKey 分类产品
         */

        if(!productList.isEmpty()){
            for (Product2 pd : productList){
                String uniKey = pd.Plan_Term__c.left(4)+':'+pd.Category3__c+':'+pd.Category4__c;

                if ('吸引活检针' == pd.Category4__c && 'EUS' == pd.Category3__c) {
                    if (pd.Asset_Model_No__c.startsWith('NA-U200H')) {
                        uniKey = pd.Plan_Term__c.left(4) + ':' + pd.Category3__c + ':吸引活检针-EZ3P';
                    } else {
                        uniKey = pd.Plan_Term__c.left(4) + ':' + pd.Category3__c + ':吸引活检针-EZ3P以外';
                    }
                } else if ('先端系粘膜切开刀' == pd.Category4__c && 'ESD' == pd.Category3__c) {
                    if (pd.Asset_Model_No__c.startsWith('KD-655')) {
                        uniKey = pd.Plan_Term__c.left(4) + ':' + pd.Category3__c + ':先端系粘膜切开刀-DualJ';
                    } else {
                        uniKey = pd.Plan_Term__c.left(4) + ':' + pd.Category3__c + ':先端系粘膜切开刀-DualJ以外';
                    }
                }

                if(uniKeyToPDListMap.get(uniKey) == null){
                    uniKeyToPDListMap.put(uniKey,new List<Product2>());
                }
                List<Product2> pdList = uniKeyToPDListMap.get(uniKey);
                pdList.add(pd);
            }
        }
        /*
         *  从产品分类价格表筛选本次执行中涉及的类目
         */
        Map<String,Product_CategoryPrice_Table__c> PCPTableMap = new Map<String,Product_CategoryPrice_Table__c>();
        Product_CategoryPrice_Table__c [] pcts = [
                SELECT Id, UniqueKey__c, Product_Amount__c, Product_Total_Price__c
                FROM Product_CategoryPrice_Table__c
                WHERE UniqueKey__c IN :uniKeyToPDListMap.keySet()
        ];

        for(Product_CategoryPrice_Table__c pct: pcts) {
            PCPTableMap.put(pct.UniqueKey__c,pct);
        }
        /*
         *  创建或更新每条记录的总量与总金额
         */

        for(String uniKey: uniKeyToPDListMap.keySet()) {
            Product_CategoryPrice_Table__c pct = PCPTableMap.get(uniKey);
            if (pct == null) {
                String [] termAndCategories = uniKey.split(':');
                pct = new Product_CategoryPrice_Table__c(
                        UniqueKey__c = uniKey,
                        OCM_Term__c = termAndCategories[0],
                        Category3__c = termAndCategories[1],
                        Category4__c = termAndCategories[2],
                        Product_Total_Price__c = 0,
                        Product_Amount__c = 0
                );
                PCPTableMap.put(uniKey, pct);
            }
            Decimal totalPrice = pct.Product_Total_Price__c;
            Decimal amount = pct.Product_Amount__c;
            List<Product2> pdList = uniKeyToPDListMap.get(uniKey);
            for (Product2 pd : pdList) {
                totalPrice += pd.Intra_Trade_List_RMB__c;
                amount++;
            }
            pct.put('Product_Total_Price__c', totalPrice);
            pct.put('Product_Amount__c', amount);
            // Decimal avg = Math.floor((totalPrice / amount * 0.7)*100+0.5) / 100.0;
            // pct.put('Category4_5_Avg_Price__c',avg);
        }

        Database.UpsertResult[] urList = Database.upsert(PCPTableMap.values(),Product_CategoryPrice_Table__c.UniqueKey__c,false);
        Integer i = 0;
        for(Database.UpsertResult ur : urList) {
            if(ur.isSuccess()){
                successCount++;
            }
            else{
                failedCount++;
                for (Database.Error err : ur.getErrors()){
                    String msg = 'UniqueKey :' + PCPTableMap.values()[i].UniqueKey__c + ' ; '
                        + err.getStatusCode() + '; '
                        + err.getFields() + ' ; '
                        + err.getMessage();
                    errMsgBody += msg + '\n';
                }
            }
            i++;
        }
        
        executedCount += productList.size();
        System.debug('ET_Product_CategoryPrice_Table_Batch execute end');
    }
    global void finish(Database.BatchableContext BC){
        System.debug('ET_Product_CategoryPrice_Table_Batch finish method start');

        String title = '产品分类价格表 Batch';
        BatchEmailUtil eb = new BatchEmailUtil();
        String[] emailList = new String[] {};
        // 失败件数为0 寄出成功的mail
        if (failedCount == 0 && totalCount == executedCount) {
            String emailLabel = 'BatchNotify';
            for (OrgWideEmailAddress tmpEmailObj : [SELECT Id, Address, DisplayName 
                FROM OrgWideEmailAddress
                WHERE DisplayName = :emailLabel]) {
                    emailList.add(tmpEmailObj.Address);
            }
            eb.successMail(emailList, null, title, executedCount);
        }
        else {
            if (totalCount != executedCount) {
                errMsgBody += '有一部分Batch没有运行, 请确认系统管理员。\n';
            }
            eb.failedMail(title, errMsgBody, totalCount, executedCount, failedCount);
        }
        eb.send();

        System.debug('ET_Product_CategoryPrice_Table_Batch finish method end');
    }
}