global class SBGITMWebService {

    global class GeDatas {
        webservice NFMUtil.Monitoring Monitoring;
        webservice SBGITMWebService.GeData[] GeData;
    }
    global class GeData {
        webservice String  ProductCode;
        webservice String  ProductDescription;
        webservice String  ProductStatus;
        webservice String  EffectiveDateTo;
        webservice String  Other1;
        webservice String  Other2;
        webservice String  Other3;
    }
    webservice static void SBGITM(GeDatas geDatas) {
        if (geDatas == null) {
            return;
        }
        NFMUtil.Monitoring Monitoring = GeDatas.Monitoring;
        if (Monitoring == null) {
            return;
        }
        BatchIF_Log__c rowData = NFMUtil.saveRowData(Monitoring, 'SBGITM', GeDatas.GeData);
        if (String.isBlank(rowData.Log__c) == false) executefuture(rowData.Id);
    }

    @future
    global static void executefuture(String rowData_Id) {
        execute(rowData_Id);
    }

    global static void execute(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 Id = :rowData_Id];
        String logstr = rowData.MessageGroupNumber__c + ' start\n';
        BatchIF_Log__c iflog = new BatchIF_Log__c();
        iflog.Type__c = 'SBGITM';
        iflog.MessageGroupNumber__c = rowData.MessageGroupNumber__c;
        iflog.Log__c = logstr;
        iflog.ErrorLog__c = '';
        insert iflog;
        String rowDataStr = NFMUtil.getRowDataStr(rowData);
        List<GeData> itemMasterList = (List<GeData>) JSON.deserialize(rowDataStr, List<GeData>.class);
        if (itemMasterList == null || itemMasterList.size() == 0) {
            return;
        }

        Savepoint sp = Database.setSavepoint();
        try {
            // 更新対応配列とMapなどをセット
            List<String> productCodeList = new List<String>();
            for (SBGITMWebService.GeData GeData : itemMasterList) {
                if (GeData.ProductCode == null || GeData.ProductCode == '') {
                    // 必須項目がない場合、処理と飛ばす
                    continue;
                }
                productCodeList.add(GeData.ProductCode);
            }
            List<Product2> prdList = [select Id,
                                            ProductCode,
                                            Description,
                                            ProductStatus__c,
                                            EffectiveDateTo__c
                                        from Product2
                                       where ProductModels__c = false and ProductCode in :productCodeList];
            Map<String, Product2> prdsMap = new Map<String, Product2>();
            for (Product2 prd : prdList) {
                prdsMap.put(prd.ProductCode, prd);
            }

            // 更新対応配列をセット
            prdList = new List<Product2>();
            Map<String, Product2> prdUpdateMap = new Map<String, Product2>();
            for (SBGITMWebService.GeData GeData : itemMasterList) {
                if (GeData.ProductCode == null || GeData.ProductCode == '') {
                    // 必須項目がない場合、処理と飛ばす
                    iflog.ErrorLog__c += 'MaterialNumber is required\n';
                    continue;
                }

                if(String.isBlank(GeData.ProductDescription)){
                    iflog.ErrorLog__c += 'Description is required:' + GeData.ProductCode  + ' \n';
                    continue;
                }

                Product2 prd = prdsMap.get(GeData.ProductCode);
                String prdName = null;
                if (prd == null) {
                    prd = new Product2();
                }
                // 項目転送のセット
                prd.ProductCode        = GeData.ProductCode;
                prd.IsActive = true;
                if (prdUpdateMap.get(prd.ProductCode) == null) {
                    prdList.add(prd);
                    prdUpdateMap.put(prd.ProductCode, prd);
                    //logstr += GeData.MaterialNumber + ' ';               // 価格表のところまとめてlogを出す
                } else {
                    prd = prdUpdateMap.get(prd.ProductCode);
                }

                // 中文名称が転送してきた場合
                prdName = GeData.ProductDescription;
                if (prdName != null) {
                    // デフォルト値
                    prd.Name = prdName;
                    String alternative_Products = null;
                    String nDM_Model_No = null; 
                    prd.Name = prdName.trim();

                    // 型番:代替品::中文名称 のパターン
                    //Pattern pt = Pattern.compile('(.*):(.*)::(.*)');
                    //Matcher mc = pt.matcher(prdName);
                    //if (mc.matches() == false
                    //        && ((prd.Name.indexOf(':') >= 0 && prd.Name.indexOf(':') != prd.Name.indexOf('::'))
                    //                || (prd.Name.indexOf('：') >= 0 && prd.Name.indexOf('：') != prd.Name.indexOf('：：'))
                    //           )
                    //) {
                    //    // 型番::中文名称 のパターン
                    //    pt = Pattern.compile('(.*):(.*)');
                    //    mc = pt.matcher(prdName);
                    //    if (mc.matches()) {
                    //        nDM_Model_No = mc.group(1).trim(); 
                    //        prd.Name = mc.group(2).trim();
                    //        prd.Product_ECCode__c = nDM_Model_No;
                    //        System.debug('mc is1' + mc);
                    //        System.debug('prdName is1' + prdName);
                    //        System.debug('nDM_Model_No is1' + nDM_Model_No);
                    //    } else {
                    //        pt = Pattern.compile('(.*)：(.*)');
                    //        mc = pt.matcher(prdName);
                    //        if (mc.matches()) {
                    //            nDM_Model_No = mc.group(1).trim();
                    //            prd.Name =  mc.group(2).trim();
                    //            prd.Product_ECCode__c = nDM_Model_No;
                    //            System.debug('mc is2' + mc);
                    //            System.debug('prdName is2' + prdName);
                    //            System.debug('nDM_Model_No is2' + nDM_Model_No);
                    //        }
                    //    }
                    //}
                    
                    if(prdName.indexOf(':') < 0 && prdName.indexOf('：') < 0){
                        prd.Product_ECCode__c = GeData.ProductCode;
                    }
                    else{
                        Integer max = -1;
                        Integer min = 100000;
                        Integer starh = prdName.indexOf(':');
                        if(starh >= 0){
                            if(min > starh){
                                min = starh;
                            }
                        }
                        Integer stara = prdName.indexOf('：');
                        if(stara >= 0){
                            if(min > stara){
                                min = stara;
                            }
                        }
                        Integer endh = prdName.lastIndexOf(':');
                        if(endh >= 0){
                            if(max < endh){
                                max = endh;
                            }
                        }
                        Integer enda = prdName.lastIndexOf('：');
                        if(enda >= 0){
                            if(max < enda){
                                max = enda;
                            }
                        }
                        prd.Product_ECCode__c = prdName.substring(0,min);
                        prd.Name =  prdName.substring(max+1,prdName.length());
                    }
                    if (GeData.ProductCode != null) {
                        prd.ProductCode = GeData.ProductCode;
                    }
                    if (GeData.ProductDescription != null) {
                        prd.Description = GeData.ProductDescription;
                    }
                    if (GeData.ProductStatus != null) {
                        prd.ProductStatus__c = GeData.ProductStatus;
                    }
                    if (GeData.EffectiveDateTo != null) {
                        prd.EffectiveDateTo__c = NFMUtil.parseStr2Date(GeData.EffectiveDateTo, true);
                    }
                }
            }
            if (prdList.size() > 0) {
                logstr += 'Execute Record:' + prdList.size() + '\n';
                upsert prdList;
                // PricebookEntryにデータがない場合insertする、CNYとUSDのみ
                Pricebook2 pricebook = ControllerUtil.getStandardPricebook();
         
                    String pricebookId = pricebook.Id;
                    List<PricebookEntry> pbeList = [Select Product2Id, CurrencyIsoCode, UnitPrice, Pricebook2Id From PricebookEntry where Product2Id in: prdList and Pricebook2Id = :pricebookId order by Product2Id, CurrencyIsoCode];
                    List<PricebookEntry> pbeInsertList = new List<PricebookEntry>();
                    Map<String, PricebookEntry> rmbMap = new Map<String, PricebookEntry>();
                    Map<String, PricebookEntry> usdMap = new Map<String, PricebookEntry>();
                    for (PricebookEntry pbe : pbeList) {
                        if (pbe.CurrencyIsoCode == 'CNY') {
                            rmbMap.put(pbe.Product2Id, pbe);
                        } else if (pbe.CurrencyIsoCode == 'USD') {
                            usdMap.put(pbe.Product2Id, pbe);
                        }
                    }
                    for (Product2 prd : prdList) {
                        logstr += prd.ProductCode;
                        if (rmbMap.get(prd.Id) == null) {
                            PricebookEntry pbe = new PricebookEntry();
                            pbe.Pricebook2Id    = pricebookId;
                            pbe.Product2Id      = prd.Id;
                            pbe.CurrencyIsoCode = 'CNY';
                            pbe.UnitPrice       = 0;
                            pbe.IsActive        = prd.IsActive;
                            pbeInsertList.add(pbe);
                            logstr += ' add(CNY_0)';
                        }
                        if (usdMap.get(prd.Id) == null) {
                            PricebookEntry pbe = new PricebookEntry();
                            pbe.Pricebook2Id    = pricebookId;
                            pbe.Product2Id      = prd.Id;
                            pbe.CurrencyIsoCode = 'USD';
                            pbe.UnitPrice       = 0;
                            pbe.IsActive        = prd.IsActive;
                            pbeInsertList.add(pbe);
                            logstr += ' add(USD_0)';
                        }
                        logstr += ' ';
                    }
                    if (pbeInsertList.size() > 0) {
                        logstr += 'Execute Record2:' + pbeInsertList.size() + '\n';
                        insert pbeInsertList;
                    }
            }
            logstr += '\nend';
            rowData.retry_cnt__c = 0;
        }catch(Exception ex){
            // エラーが発生した場合
            Database.rollback(sp);
            System.debug(Logginglevel.ERROR, 'SBGITM_' + rowData.MessageGroupNumber__c + ':' + ex.getMessage());
            System.debug(Logginglevel.ERROR, 'SBGITM_' + 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;
    }
}