@RestResource(urlMapping='/SBG004/*')
global with sharing class SBG004Rest  {
	public class SBG004ResrException extends Exception {}
    global class GeDatasRest {
        public GeDatas GeDatas;
    }

    global class GeDatas {
        public NFMUtil.Monitoring Monitoring;
        public SBG004Rest.GeData[] GeData;
    }
    global class GeData {
        public String  ProductCode;
        public String  Currency_x;
        public String  ProductSegment;
        public String  TradeType;
        public String  MachineParts;
        public String  SalesChannel;
        public Decimal CostPrice;
        public String  EffectiveDateFrom;
        public String  EffectiveDateTo;
        public String  PurposeOfAdvice;
        public String  Other1;
        public String  Other2;
        public String  Other3;
    }

    @HttpPost
    global static void execute() {

        // 取得接口传输内容
        String strData = RestContext.request.requestBody.toString();
        GeDatasRest ges = (GeDatasRest) JSON.deserializeStrict(strData, GeDatasRest.class);

        if (ges == null ) {
            return;
        }

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

        BatchIF_Log__c rowData = NFMUtil.saveRowData(Monitoring, 'SBG004', ges.GeDatas.GeData);
        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 = scope[0];
        //String logstr = rowData.MessageGroupNumber__c + ' ' + startIndex + '/' + dataLength + ' start\n';
        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 Id = :rowData_Id];
       
        String logstr = '';
        BatchIF_Log__c iflog = new BatchIF_Log__c();
        iflog.Type__c = 'SBG004';
        iflog.MessageGroupNumber__c = rowData.MessageGroupNumber__c;
        //iflog.Log__c = logstr;
        iflog.ErrorLog__c = '';
        insert iflog;
        String rowDataStr = NFMUtil.getRowDataStr(rowData);
        List<GeData> purchasePriceList2 = (List<GeData>) JSON.deserialize(rowDataStr, List<GeData>.class);
        if (purchasePriceList2 == null || purchasePriceList2.size() == 0) {
            return;
        }
        List<String> productCodeList = new List<String>();
        List<String> prekeys = new List<String>();
        for (Integer i = 0; i <purchasePriceList2.size(); i++) 
        {    GeData data = purchasePriceList2[i];
            if (data.SalesChannel == '99') {
                prekeys.add(data.ProductSegment + '_' + data.TradeType + '_dealer_' + data.MachineParts + '_' + data.ProductCode + '_' + data.Currency_x);
                prekeys.add(data.ProductSegment + '_' + data.TradeType + '_direct_' + data.MachineParts + '_' + data.ProductCode + '_' + data.Currency_x);
            } else {
                String salesChannel = data.SalesChannel == '41' ? 'dealer' : 'direct';
                prekeys.add(data.ProductSegment + '_' + data.TradeType + '_' + salesChannel + '_' + data.MachineParts + '_' + data.ProductCode + '_' + data.Currency_x);
            }
            productCodeList.add(purchasePriceList2.get(i).ProductCode);
        }

        Map <String,PricebookEntry > premap = new Map<String,PricebookEntry >();
        for(PricebookEntry pre : [Select Id,Name,KEY__c,EffectiveDateFrom1__c,EffectiveDateFrom2__c,UnitPrice,
                                 EffectiveDateTo1__c,EffectiveDateTo2__c,CostPrice1__c,CostPrice2__c,SalesPrice1__c,SalesPrice2__c
                                 from PricebookEntry where KEY__c in:prekeys])
        {
            premap.put(pre.KEY__c,pre);
        }

        Map <String,Pricebook2 > prebookmap = new Map<String,Pricebook2 >();
        for(Pricebook2 pre : [Select Id,Name,MachineParts__c,ProductSegment__c,SalesChannel__c,TradeType__c,isActive
                                 from Pricebook2 where IsStandard = false])
        {
            prebookmap.put(pre.ProductSegment__c + '_' + pre.TradeType__c + '_' + pre.SalesChannel__c + '_' + pre.MachineParts__c,pre);
        }
        System.debug('prebookis' + prebookmap);


        Map<String, Product2> prdsMap = new Map<String, Product2>();
        for (Product2 prd : [select Id, ProductCode, Product_ECCode__c,
                                         EffectiveDateTo__c,
                                         ProductModels__c,
                                         ProductStatus__c
                                    from Product2
                                   where ProductModels__c = false and ProductCode in :productCodeList]
        ) {
            prdsMap.put(prd.ProductCode, prd);
        }

        Savepoint sp = Database.setSavepoint();
        try {
            List<PricebookEntry> pres = new List<PricebookEntry>();
            Set<String> updPresSet = new Set<String>();
            Boolean retrycntFlag = false;
            for (Integer i = 0; i < purchasePriceList2.size(); i++) {
                //purchasePriceList.add(purchasePriceList2.get(i));
                GeData data = purchasePriceList2.get(i);
                if (data.PurposeOfAdvice == '1') {
                        data.EffectiveDateTo = NFMUtil.formatDate2Str(Date.today().addDays(-1));
                }
                if (String.isBlank(purchasePriceList2.get(i).ProductCode) == false) {
                    if (data.ProductCode == null || data.ProductCode == '') {
                        iflog.ErrorLog__c += 'ProductCode is required\n';
                        continue;
                    }
                    if (data.ProductSegment == null || data.ProductSegment == '') {
                        iflog.ErrorLog__c += '[' + data.ProductCode + ']PriceType is required\n';
                        continue;
                    }
                    if (data.Currency_x == null || data.Currency_x == '') {
                        iflog.ErrorLog__c += '[' + data.ProductCode + ']Currency is required\n';
                        continue;
                    }
                    if (data.EffectiveDateFrom == null || data.EffectiveDateFrom == '') {
                        iflog.ErrorLog__c += '[' + data.ProductCode + ']EffectiveDateFrom is required\n';
                        continue;
                    }
                    if (data.EffectiveDateTo == null || data.EffectiveDateTo == '') {
                        iflog.ErrorLog__c += '[' + data.ProductCode + ']EffectiveDateTo is required\n';
                        continue;
                    }
                    if(prdsMap.get(data.ProductCode) == null)
                    {
                        iflog.ErrorLog__c += 'Product[' + data.ProductCode + ']NotExist\n';
                        retrycntFlag = true;
                        continue;
                    }

                    if(data.SalesChannel == '99')
                    {
                        String pdedikey = data.ProductSegment + '_' + data.TradeType + '_' + 'direct' + '_' + data.MachineParts + '_' + data.ProductCode + '_' + data.Currency_x;
                        String pbedekey = data.ProductSegment + '_' + data.TradeType + '_' + 'dealer' + '_' + data.MachineParts + '_' + data.ProductCode + '_' + data.Currency_x;
                        String pddikey = data.ProductSegment + '_' + data.TradeType + '_' + 'direct' + '_' + data.MachineParts;
                        String pddekey = data.ProductSegment + '_' + data.TradeType + '_' + 'dealer' + '_' + data.MachineParts;
                        PricebookEntry pre1 = setpricebookec(data,premap,prdsMap.get(data.ProductCode).Id,prebookmap.get(pddikey),pdedikey,updPresSet);
                        PricebookEntry pre2 = setpricebookec(data,premap,prdsMap.get(data.ProductCode).Id,prebookmap.get(pddekey),pbedekey,updPresSet);

                        pres.add(pre1);
                        pres.add(pre2);

                    }
                    else {
                        String salesChannel = data.SalesChannel == '41' ? 'dealer' : 'direct';
                        String pbekey = data.ProductSegment + '_' + data.TradeType + '_' + salesChannel + '_' + data.MachineParts + '_' + data.ProductCode + '_' + data.Currency_x;
                        String pbkey = data.ProductSegment + '_' + data.TradeType + '_' + salesChannel + '_' + data.MachineParts;
                        System.debug(prdsMap.get(data.ProductCode));
                        System.debug(pbekey);
                        System.debug(prebookmap);

                        PricebookEntry pre1 = setpricebookec(data,premap,prdsMap.get(data.ProductCode).Id,prebookmap.get(pbkey),pbekey,updPresSet);
                        pres.add(pre1);
                    }

                }
            }
      
            System.debug(logstr);
            logstr += 'Execute Record:' + pres.size() + '\n';
            if(pres.size()>0) {
                upsert(pres);
            }
            logstr += '\nend';
            
            if (retrycntFlag) {
                LogAutoSend(rowData,batch_retry_max_cnt,iflog);
            } else {
               rowData.retry_cnt__c = 0; 
            }

        } catch(Exception ex) {
            // エラーが発生した場合
            Database.rollback(sp);
            System.debug(ex);
            System.debug(Logginglevel.ERROR, 'SBG004_' + rowData.MessageGroupNumber__c + ':' + ex.getMessage());
            System.debug(Logginglevel.ERROR, 'SBG004_' + 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++;
                LogAutoSendScheduleProduct.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;
    }
    global static void LogAutoSend (BatchIF_Log__c rowData,Integer batch_retry_max_cnt,BatchIF_Log__c iflog) {
        system.debug('LogAutoSend---Start');
        if (rowData.retry_cnt__c == null) rowData.retry_cnt__c = 0;
        
        if (rowData.retry_cnt__c < batch_retry_max_cnt){
            rowData.retry_cnt__c++;
            LogAutoSendScheduleProduct.assignOneMinute();
        }
        if (rowData.retry_cnt__c >= batch_retry_max_cnt){
            rowData.ErrorLog__c = iflog.ErrorLog__c+'错误次数已经超过自动收信设定的最大次数，请手动收信';
        }

        update rowData;

    }
    global static PricebookEntry setpricebookec(GeData data,Map<String,PricebookEntry> premap,String productid,Pricebook2 pricebook2,String pbekey, Set<String> updPresSet) {
        System.debug('setpricebookec start productid=' + productid);
        System.debug('setpricebookec start Pricebook2id=' + pricebook2.Id);
        Date dateFrom = NFMUtil.parseStr2Date(data.EffectiveDateFrom, false);
        Date dateTo = NFMUtil.parseStr2Date(data.EffectiveDateTo, true);
        System.debug('fram' + dateFrom);
        System.debug('to' + dateTo);
        String curr = data.Currency_x == 'RMB' ? 'CNY' : data.Currency_x;
        System.debug('Currency_x is ' + curr);
        if (updPresSet.contains(pbekey))
        {
             throw new SBG004ResrException(pbekey + ' is doubled in message file.');
        }

        PricebookEntry pre = premap.get(pbekey);
        if(pre != null){
            System.debug('fram111' + pre.EffectiveDateFrom1__c);
            System.debug('to111' + pre.EffectiveDateTo1__c);
        }

        // TODO CurrencyIsoCode 等
        // UnitPrice = 0
        if (pre == null) {
            pre = new PricebookEntry(KEY__c =  pbekey,
                                     CostPrice1__c = data.CostPrice,
                                     CurrencyIsoCode = curr,
                                     EffectiveDateFrom1__c = dateFrom,
                                     EffectiveDateTo1__c = dateTo,
                                     UnitPrice = 0,
                                     Product2Id = productid,
                                     Pricebook2id = pricebook2.Id,
                                     isActive = pricebook2.isActive,
                                     UseStandardPrice = false);
        }
        else if (pre.EffectiveDateFrom1__c == null || pre.EffectiveDateTo1__c < Date.today() || pre.EffectiveDateFrom1__c == dateFrom) {
            pre = new PricebookEntry(KEY__c =  pbekey,
                                     Id = pre.Id,
                                     CostPrice1__c = data.CostPrice,
                                     CurrencyIsoCode = curr,
                                     EffectiveDateFrom1__c = dateFrom,
                                     EffectiveDateTo1__c = dateTo,
                                     UnitPrice = 0,
                                     Product2Id = productid,
                                     Pricebook2id = pricebook2.Id,
                                     isActive = pricebook2.isActive,
                                     UseStandardPrice = false);
        }
        else if(pre.EffectiveDateFrom2__c == null || pre.EffectiveDateTo2__c < Date.today() || pre.EffectiveDateFrom2__c == dateFrom) {
            pre = new PricebookEntry(KEY__c =  pbekey,
                                     Id = pre.Id,
                                     CostPrice2__c = data.CostPrice,
                                     CurrencyIsoCode = curr,
                                     EffectiveDateFrom2__c = dateFrom,
                                     EffectiveDateTo2__c = dateTo,
                                     UnitPrice = 0,
                                     Product2Id = productid,
                                     Pricebook2id = pricebook2.Id,
                                     isActive = pricebook2.isActive,
                                     UseStandardPrice = false);
        }
        else if(pre.EffectiveDateFrom1__c < pre.EffectiveDateFrom2__c) {
            pre = new PricebookEntry(KEY__c =  pbekey,
                                     Id = pre.Id,
                                     CostPrice1__c = data.CostPrice,
                                     CurrencyIsoCode = curr,
                                     EffectiveDateFrom1__c = dateFrom,
                                     EffectiveDateTo1__c = dateTo,
                                     UnitPrice = 0,
                                     Product2Id = productid,
                                     Pricebook2id = pricebook2.Id,
                                     isActive = pricebook2.isActive,
                                     UseStandardPrice = false);
        }
        else {
            pre = new PricebookEntry(KEY__c =  pbekey,
                                     Id = pre.Id,
                                     CostPrice2__c = data.CostPrice,
                                     CurrencyIsoCode = curr,
                                     EffectiveDateFrom2__c = dateFrom,
                                     EffectiveDateTo2__c = dateTo,
                                     UnitPrice = 0,
                                     Product2Id = productid,
                                     Pricebook2id = pricebook2.Id,
                                     isActive = pricebook2.isActive,
                                     UseStandardPrice = false);
        }
        updPresSet.add(pbekey);
        return pre;
    }
}