/**********************************************************************
 * 
 *
 * @url: /services/apexrest/rest
 * @data:
 *  {
        

    
    }
*************************************************************************/
@RestResource(urlMapping='/NFM211/*')
global with sharing class NFM211Rest {

    // global class GeDatasRest {
    //     public GeDatas GeDatas;
    // }

    //定义Monitoring + header
    global class GeDatas{
        public NFMUtil.Monitoring Monitoring;
        public Header[] Header;
    }

    //定义促销方案/一般产品header
    global class Header{
        //定义促销方案/一般产品产品行
        public Items[] Items;
        //SFDC一个表  SPO两个表 需要拼接ID 即SpoId = SpoId+Category
        public String SpoID;                    //促销方案/一般产品ID（SPO）
        public String PromotionNo;              //促销方案/一般产品代码
        public String Description;              //促销方案描述
        public String Memo;                     //促销方案具体内容
        public String Category;                 //分类 (1：促销政策 2：促销价格产品)
        public String DateFrom;                 //有效期（从）
        public String DateTo;                   //有效期（至）
        public boolean IfContainsGuarantee;     //是否包含多年保价格
        public boolean IsCheckProductCount;     //产品型号是否固定
        public Decimal Price;                   //促销价格
        public String ProductType;              //产品类别
        public boolean ifNecessary;             //是否强制匹配
        public Integer OrderNo;                 //匹配优先度
        public String ApplyStatus;              //审批状态


    }
    //促销方案/一般产品产品行
    global class Items{
        
        public String Model;                    //产品型号
        public Integer Quantity;                //数量
    }

    @HttpPost
    global static void execute() {
        // 取得接口传输内容
        String strData = RestContext.request.requestBody.toString();
        GeDatas ges = (GeDatas) JSON.deserializeStrict(strData, GeDatas.class);
        // GeDatas ges =gesRest.GeDatas;
        if (ges == null ) {
            return;
        }

        NFMUtil.Monitoring Monitoring = ges.Monitoring;
        if (Monitoring == null) {
            return;
        }

        BatchIF_Log__c rowData = NFMUtil.saveRowData(Monitoring, 'NFM211', ges.Header);
        if (String.isBlank(rowData.Log__c) == false) {
            executefuture(rowData.Id);
        }
        // JSONを戻す
        RestResponse res = RestContext.response;
        res.addHeader('Content-Type', 'application/json');
        res.statusCode = 200;
        //String jsonResponse = '{"status": "Success", "Message":'  + gedata + '}';
        String jsonResponse = '{"status": "Success", "Message":""}';
        res.responseBody = blob.valueOf(jsonResponse);
        return;
    }
    @future
    global static void executefuture(String rowData_Id) {
        main(rowData_Id);
    }

    global static void main(String rowData_Id) {

        Integer batch_retry_max_cnt = Integer.valueOf(System.Label.batch_retry_max_cnt);
        BatchIF_Log__c rowData = [Select Id, Name, Log__c, ErrorLog__c, Log2__c, Log3__c, Log4__c, Log5__c, Log6__c, Log7__c, Log8__c, Log9__c, Log10__c, Log11__c, Log12__c, MessageGroupNumber__c,retry_cnt__c from BatchIF_Log__c where RowDataFlg__c = true and Type__c='NFM211' and Id = :rowData_Id];
        String logstr = rowData.MessageGroupNumber__c + ' start\n';
        BatchIF_Log__c iflog = new BatchIF_Log__c();
        iflog.Type__c = 'NFM211';
        iflog.MessageGroupNumber__c = rowData.MessageGroupNumber__c;
        iflog.Log__c = logstr;
        iflog.ErrorLog__c = '';
        insert iflog;

        String rowDataStr = NFMUtil.getRowDataStr(rowData);
        List<Header> geDataList = (List<Header>) JSON.deserialize(rowDataStr, List<Header>.class);
        if (geDataList == null || geDataList.size() == 0) {
            return;
        }
        //检索促销方案记录类型，并制作map
        Map<String,String> recordTypeMap = new Map<String,String>();
        if(Schema.SObjectType.PromotionHead__c.getRecordTypeInfosByDeveloperName().get('Promotion').getRecordTypeId()!=null){
            recordTypeMap.put('促销政策',Schema.SObjectType.PromotionHead__c.getRecordTypeInfosByDeveloperName().get('Promotion').getRecordTypeId());
        }
        if(Schema.SObjectType.PromotionHead__c.getRecordTypeInfosByDeveloperName().get('NormalProduct').getRecordTypeId()!=null){
            recordTypeMap.put('促销价格产品',Schema.SObjectType.PromotionHead__c.getRecordTypeInfosByDeveloperName().get('NormalProduct').getRecordTypeId());
        }
        if(Schema.SObjectType.PromotionHead__c.getRecordTypeInfosByDeveloperName().get('Authorizer').getRecordTypeId()!=null){
            recordTypeMap.put('固定价格',Schema.SObjectType.PromotionHead__c.getRecordTypeInfosByDeveloperName().get('Authorizer').getRecordTypeId());
        }
        //head 必填验证 如果有则不生成数据
        Map<String,String> skippedMap = new Map<String,String>();

        //定义促销方案/一般产品Id List
        List<String> spoIdList = new List<String>();
        //构建促销方案/一般产品map,key：spoid+Category value:PromotionHead__c
        Map<String,PromotionHead__c> pHMaps = new Map<String,PromotionHead__c>();
        //构建促销方案/一般产品产品行List
        List<PromotionProduct__c> promotionProductList = new List<PromotionProduct__c>();
        //构建促销方案/一般产品，产品行map
        //Map<String,List<PromotionProduct__c>> pPMaps = new Map<String,List<PromotionProduct__c>>();
        Savepoint sp = Database.setSavepoint();
        try{
            //验证必填
            for (Header gda :geDataList) {
                //先拼接key
                if(String.isNotBlank(gda.SpoID)){
                    gda.SpoID = gda.SpoID+gda.Category;
                    spoIdList.add(gda.SpoID);
                }
                //转成json串
                String jsonStr = JSON.serialize(gda);
                system.debug('jsonStr:'+jsonStr);
                //按字段拆分 存入map key value 公共参数 因为value值类型不同 无法定义
                Map<String,Object>  headMap = (Map<String,Object>) JSON.deserializeUntyped(jsonStr);
                system.debug('headMap:'+headMap);

                /**
                 * 验证代码优化 wql 2021/10/27 start
                 * param1：已知必填字段
                 * param2：所有字段map
                 */
                //列举一部分 无条件判断的必填  写死是因为 接口文档一般会给出哪些字段必填
                // List<String> checkList =new List<String>{'SpoID','PromotionNo', 'IfContainsGuarantee', 'IsCheckProductCount', 'Price','Description','Memo'};
                // for(Integer i=0;i<checkList.size();i++){
                //     //这里需要转一下 因为肯定所有的字段类型不一样 最好用SObject
                //     if(headMap.get(checkList[i])==null){
                //         //存入必填报错信息
                //         checkSkipped(skippedMap,checkList[i],headMap,iflog);
                //         continue;
                //     }
                // }
                
                //验证必填字段
                //SFDC-->SPO 一对2 拼接id
                if(String.isBlank(gda.SpoID)){
                    //存入必填报错信息
                    checkSkipped(skippedMap,'SpoID',headMap,iflog);
                    continue;
                }
                //促销方案/一般产品代码 必填验证
                if(String.isBlank(gda.PromotionNo)){
                    //存入必填报错信息
                    checkSkipped(skippedMap,'PromotionNo',headMap,iflog);
                    continue;
                }
                if (String.isNotBlank(gda.Category)) {
                    //check start
                    if(gda.Category.equals('促销政策')){
                        //如果是促销政策,是否包含多年保价格必填
                        if(gda.IfContainsGuarantee ==null){
                            //存入必填报错信息
                            checkSkipped(skippedMap,'IfContainsGuarantee',headMap,iflog);
                            continue;
                        }
                        //如果是促销政策,产品型号是否固定必填
                        if(gda.IsCheckProductCount ==null){
                            //存入必填报错信息
                            checkSkipped(skippedMap,'IsCheckProductCount',headMap,iflog);
                            continue;
                        }
                        //如果是促销政策,促销价格必填
                        if(gda.Price ==null){
                            //存入必填报错信息
                            checkSkipped(skippedMap,'Price',headMap,iflog);
                            continue;
                        }
                        //促销方案描述 必填验证
                        if(gda.Description ==null){
                            //存入必填报错信息
                            checkSkipped(skippedMap,'Description',headMap,iflog);
                            continue;
                        }
                        //促销方案具体内容 必填验证
                        if(gda.Memo ==null){
                            //存入必填报错信息
                            checkSkipped(skippedMap,'Memo',headMap,iflog);
                            continue;
                        }
                        //促销方案有效期从 必填验证
                        if(gda.DateFrom ==null){
                            //存入必填报错信息
                            checkSkipped(skippedMap,'DateFrom',headMap,iflog);
                            continue;
                        }
                        //促销方案有效期至 必填验证
                        if(gda.DateTo ==null){
                            //存入必填报错信息
                            checkSkipped(skippedMap,'DateTo',headMap,iflog);
                            continue;
                        }
                    }else if(gda.Category.equals('促销价格产品')){
                        //如果是促销价格产品,产品类别必填
                        if(String.isBlank(gda.ProductType)){
                            //存入必填报错信息
                            checkSkipped(skippedMap,'ProductType',headMap,iflog);
                            continue;
                        }
                        //如果是促销价格产品,是否强制匹配必填
                        if(gda.ifNecessary ==null){
                            //存入必填报错信息
                            checkSkipped(skippedMap,'ifNecessary',headMap,iflog);
                            continue;
                        }
                        //如果是促销价格产品,匹配优先度必填
                        if(gda.OrderNo ==null){
                            //存入必填报错信息
                            checkSkipped(skippedMap,'OrderNo',headMap,iflog);
                            continue;
                        }
                    }
                    //check end
                }else{
                    //存入必填报错信息
                    checkSkipped(skippedMap,'Category',headMap,iflog);
                    continue;
                }
                //审批状态 必填验证
                if(gda.ApplyStatus ==null){
                    //存入必填报错信息
                    checkSkipped(skippedMap,'ApplyStatus',headMap,iflog);
                    continue;
                }
            }
            List<PromotionHead__c> promotionHeadList = new List<PromotionHead__c>();
            //临时 的upsertList
            List<PromotionHead__c> upSertTempPromotionHeadList = new List<PromotionHead__c>();
            //最终的upsertList
            List<PromotionHead__c> upSertPromotionHeadList = new List<PromotionHead__c>();
            if(spoIdList.size()>0){
                //Query 根据接口的SpoId检索所有促销方案/一般产品
                promotionHeadList = [Select id,SpoId__c,Province__c,Area__c,if_Fix__c,PromotionNo__c,Price_CNY__c,Price_USD__c,if_Contain_Nod__c,NormalDiscount__c
                                    ,Category__c,Memo__c,Description__c,Status__c,DateTo__c,DateFrom__c,HospitalLevel__c,ProductCategory__c,ProductType__c
                                    ,Contract__c,ApplyStatus__c,GuaranteeDiscount__c,Agency__c,OrderNo__c,ifNecessary__c  from PromotionHead__c where SpoId__c=:spoIdList];

                if(promotionHeadList.size()>0){
                    for(PromotionHead__c p : promotionHeadList){
                        pHMaps.put(p.SpoId__c, p);
                    }
                }
                //生成促销方案/一般产品主数据
                for(Header infoH :geDataList){
                    PromotionHead__c tempPromotionHead = pHMaps.get(infoH.SpoID);
                    if(infoH.SpoID!=null){
                        if(tempPromotionHead==null){
                            tempPromotionHead = new PromotionHead__c();
                            tempPromotionHead = SetPromotionHead(tempPromotionHead,infoH,recordTypeMap);
                            checkPH( tempPromotionHead, upSertTempPromotionHeadList, iflog, infoH );
                        }else{
                            tempPromotionHead = SetPromotionHead(tempPromotionHead,infoH,recordTypeMap);
                            checkPH( tempPromotionHead, upSertTempPromotionHeadList, iflog, infoH );
                        }

                    }
                }
                

            }
            //存放 spoid,主数据id
            Map<String,String>  pHeadMap= new Map<String,String>();
            System.debug('skippedMap:'+skippedMap);
            if (upSertTempPromotionHeadList.size() > 0) {
                System.debug('upSertTempPromotionHeadList1:'+upSertTempPromotionHeadList);
                //判断需要更新的list中是否有head头必填报错的数据 有则不需要生成
                for(PromotionHead__c prom:upSertTempPromotionHeadList){
                    if(!skippedMap.containsKey(prom.SpoId__c)){
                        upSertPromotionHeadList.add(prom);
                    }
                }
                system.debug('upSertPromotionHeadList'+upSertPromotionHeadList);
                //正常更新
                if(upSertPromotionHeadList.size() > 0){
                    upsert upSertPromotionHeadList ;
                    //根据sid，促销方案/一般产品 生成map 用于产品行用
                    for(PromotionHead__c pHead:upSertPromotionHeadList){
                        pHeadMap.put(pHead.SpoId__c,pHead.id);
                    }
                }
                
            }
            system.debug('pHeadMap:'+pHeadMap);
            //促销政策 产品行
            for(Header infoH :geDataList){
                if(infoH.Items!=null){
                    for(Items pp :infoH.Items){
                        PromotionProduct__c pProduct = new PromotionProduct__c();
                        //生成产品行
                        pProduct=SetPromotionPrdouct(pProduct,infoH,pp,pHeadMap,iflog);
                        if(pProduct!=null){
                            promotionProductList.add(pProduct);                        
                        }
                    }
                    //目前可以不用 如果以后需要 可以for循环每次初始化list 然后存成map 最后list.addall()汇总
                    //pPMaps.put(infoH.SpoID,promotionProductList);
                }
            }
            system.debug('promotionProductList:'+promotionProductList);
            //查询 旧产品行
            List<PromotionProduct__c> promotionProductDeleteList = [select id,PromotionHead__c from PromotionProduct__c where PromotionHead__c =:pHeadMap.values()];
            //产品行 全删全增
            if(promotionProductDeleteList.size()>0){
                delete promotionProductDeleteList;
            }
            //主数据没有生成的  行项目也一定不生成
            if(promotionProductList.size()>0){
                insert promotionProductList;
            }

            logstr += '\nend';
            rowData.retry_cnt__c=0;

        }catch(Exception ex){
            Database.rollback(sp);
              System.debug(Logginglevel.ERROR, 'NFM211_' + rowData.MessageGroupNumber__c + ':' + ex.getMessage());
              System.debug(Logginglevel.ERROR, 'NFM211_' + rowData.MessageGroupNumber__c + ':' + ex.getStackTraceString());
              logstr += '\n' + ex.getMessage();
              iflog.ErrorLog__c = ex.getMessage() + '\n' + ex.getStackTraceString() + '\n' + iflog.ErrorLog__c;

              if (rowData.retry_cnt__c == null) rowData.retry_cnt__c = 0;
              if (rowData.retry_cnt__c < batch_retry_max_cnt) {
                  rowData.retry_cnt__c++;
                  LogAutoSendSchedule.assignOneMinute();
              }
              if (rowData.retry_cnt__c >= batch_retry_max_cnt) {
                  rowData.ErrorLog__c = ex.getMessage() + '\n' + ex.getStackTraceString() + '\n' + rowData.ErrorLog__c+'错误次数已经超过自动收信设定的最大次数，请手动收信';
              }
        }



        update rowData;
        iflog.Log__c = logstr;
        if (iflog.Log__c.length() > 131072) {
            iflog.Log__c = iflog.Log__c.subString(0, 131065) + ' ...';
        }
        if (iflog.ErrorLog__c.length() > 32768) {
            iflog.ErrorLog__c = iflog.ErrorLog__c.subString(0, 32760) + ' ...';
        }
        update iflog;
    }
    /* 构建促销方案/一般产品：
     * iflog 写日志
     * infoH 为 211接口数据
     * Map<String,String> recordTypeMap 记录类型
     */
    @TestVisible
    private static PromotionHead__c SetPromotionHead(PromotionHead__c tempPH,Header infoH,Map<String,String> recordTypeMap){
        //spoId 唯一
        if(String.isNotBlank(infoH.SpoID)){
            tempPH.SpoId__c = infoH.SpoID;
        }
        //促销方案/一般产品代码
        if(String.isNotBlank(infoH.PromotionNo)){
            tempPH.PromotionNo__c = infoH.PromotionNo;
            
        }
        //记录类型
        tempPH.recordTypeid  = recordTypeMap.get(infoH.Category);
        //审批状态
        tempPH.ApplyStatus__c = infoH.ApplyStatus;
        //促销方案描述
        if(String.isNotBlank(infoH.Description)){
            tempPH.Description__c = infoH.Description;
            //名称 促销政策名称 =方案描述
            tempPH.name = infoH.Description;
        }
        //促销方案具体内容
        if(String.isNotBlank(infoH.Memo)){
            tempPH.Memo__c = infoH.Memo;
        }
        //分类
        if(String.isNotBlank(infoH.Category)){
            tempPH.Category__c = infoH.Category;
            if(infoH.Category.equals('促销政策')){
                
                //有效期（从）
                if(infoH.DateFrom !=null){
                    tempPH.DateFrom__c = NFMUtil.parseStr2Date(infoH.DateFrom);
                }
                //有效期（至）
                if(infoH.DateTo !=null){
                    tempPH.DateTo__c = NFMUtil.parseStr2Date(infoH.DateTo);
                }
                //是否包含多年保价格
                if(infoH.IfContainsGuarantee !=null){
                    tempPH.if_Contain_Nod__c = infoH.IfContainsGuarantee;
                }
                //产品型号数量是否固定
                if(infoH.IsCheckProductCount !=null){
                    tempPH.if_Fix__c = infoH.IsCheckProductCount;
                }
                //促销价格(传人民币)
                if(infoH.Price !=null){
                    tempPH.Price_CNY__c = infoH.Price;
                    tempPH.Price_USD__c = infoH.Price /Decimal.valueOf(Label.Account_Exc);
                }

            }else if(infoH.Category.equals('促销价格产品')){
                //名称 一般产品名称 （10）：方案描述
                // tempPH.name = infoH.PromotionNo;
                //产品类别
                if(infoH.ProductType !=null){
                    tempPH.ProductCategory__c = infoH.ProductType;
                }
                //是否强制匹配
                if(infoH.ifNecessary !=null){
                    tempPH.ifNecessary__c = infoH.ifNecessary;
                }
                //是否包含多年保价格
                if(infoH.OrderNo !=null){
                    tempPH.OrderNo__c = infoH.OrderNo;
                }
            }
            
        }

        

        return tempPH;
    }
    /* 构建促销方案/一般产品产品行：
     * tempPP 产品行对象
     * infoH 为 211接口主数据
     * infoP 为 211接口详数据
     * pHeadMap 为 主数据SID,主数据id
     * BatchIF_Log__c iflog 日志
     */
    @TestVisible
    private static PromotionProduct__c SetPromotionPrdouct(PromotionProduct__c tempPP,Header infoH,Items infoP,Map<String,String>  pHeadMap,BatchIF_Log__c iflog){
        //促销方案/一般产品
        if(pHeadMap.get(infoH.SpoID)!=null){
            //产品型号
            if(String.isNotBlank(infoP.Model)&&infoP.Quantity!=null){
                tempPP.PromotionHead__c = pHeadMap.get(infoH.SpoID);
                tempPP.Asset_Model_No__c = infoP.Model;
                tempPP.name = infoP.Model;
                //数量
                tempPP.Quantity__c = infoP.Quantity;
                return tempPP;
            }else{
                //check 产品行 必填 (不用共通 直接生成日志即可，此条不会生成 因为return null)
                if(String.isBlank(infoP.Model)){
                    iflog.ErrorLog__c += '产品行：Model'+'[ '+ infoP.Model +' ] of BPType is required,This data is skipped.\n';
                }
                if(infoP.Quantity==null){
                    iflog.ErrorLog__c += '产品行：Quantity'+'[ '+ infoP.Quantity +' ] of BPType is required,This data is skipped.\n';
                }
                return null;
            }
        }
        return null;
    }
    /* 构建促销方案/一般产品List：UpsertPHList
     * 临时促销政策：tempPH
     * 日志内容：iflog
     * 接口数据：infoH
     */
    private static void checkPH(PromotionHead__c tempPH,
                                List<PromotionHead__c> UpsertPHList,
                                BatchIF_Log__c iflog,
                                Header infoH ) {
                                    if (infoH.SpoID != null)
                                        UpsertPHList.add(tempPH);
                                    else {
                                        iflog.ErrorLog__c += 'warning! SpoID[' + infoH.SpoID +
                                            '] SpoID  NotExist. The insert of this PromotionHead__c is skipped.\n';
                                    }

                                }
    /* 构建必填验证map：skippedMap
     * 字段名：key
     * 1条数据的字段拆分：headMap
     * 日志：iflog
     */
    private static void checkSkipped(Map<String,String> skippedMap,String key,Map<String,Object>  headMap,BatchIF_Log__c iflog) {
                             iflog.ErrorLog__c += 'SPOID:'+headMap.get('SpoID')+'--'+key+'[ '+ headMap.get(key) +' ] of BPType is required,This data is skipped.\n';
                                //如果SPOID为空 直接报错，所有数据无法执行；如果分类为空，只有此条数据不执行，其他正常执行。
                                skippedMap.put(String.valueOf(headMap.get('SpoID')), iflog.ErrorLog__c);
                                }
}