public without sharing class SBG027Controller {
    
    public class SBG027 {
        public GeDatas_element GeDatas;
    }
    
    public class GeDatas_element {
        public NFMUtil.Monitoring Monitoring;
        public GeData_element[] GeData;
    }

    public class GeData_element {
        //CBPR
        public String ZNMPA;
        //CBPR
        public String OpportunityCode;
        public String OrderCode;
        public String SalesAccountCode;
        public String EndUser;
        public String ProductSegment;
        public String TradeType;
        public String MachineParts;
        public String SalesChannel;
        public String DealerCode;
        public String DealerSalesStaffName;
        public String DeliveryDate;
        public String PaymentCondition;
        public String SpecialWarranty;
        public Decimal OlympusContractPrices;
        public Decimal Discount;
        public Decimal OlympusPriceBeforeDiscount;
        public Decimal ServiceFee;
        public String ForeignTradeCompany;
        public String SpecialDeliveryAddress;
        public String PurposeOfAdvice;
        public String Other1;
        public String Other2;
        public String Other3;
        // 跨区域销售 XHL 20210831 Start
        public String CoopAgent;//合作区域代理商Code
        public String CoopAgentPCT;//业绩拆分比例(取:后边的值*10) 
        // 跨区域销售 XHL 20210831 End 
        public GeDataDetails_element[] GeDataDetails;
        
    }

    public class GeDataDetails_element {
        public Integer DetailLine;
        public String ItemCode;
        public Integer ItemQuantity;
        
    }
    /**
     * SBG027の送信処理
     *
     * @param iflog_Id           ログテーブルのId
     * @param ordIds             送信対象商談(論理上1件のみです)
     * @param C1:Delete 2:Add(Insert) 3:Change(Update)
     */
    @future (callout=true)
    public static void callout(String iflog_Id, List<String> ordIds, Map<String, String> purposeOfAdviceMap) {
        if (ordIds == null || ordIds.size() == 0) {
            return;
        }
        //SBG027Sync.HTTPS_Port stub = new SBG027Sync.HTTPS_Port();
        //stub.timeout_x = 100000; // timeout in milliseconds
        //stub.endpoint_x = NFMUtil.SBG027_ENDPOINT;
        //stub.inputHttpHeaders_x = new Map<String, String>();
        //stub.inputHttpHeaders_x.put('Authorization', NFMUtil.Authorization);
        //if (NFMUtil.CLIENT_CERT_NAME != null) {
        //    stub.clientCertName_x = NFMUtil.CLIENT_CERT_NAME;
        //}

        // MessageGroupNumber の取得
        List<BatchIF_Log__c> iflogList = [Select Id, Name, Log__c, ErrorLog__c from BatchIF_Log__c where Id = :iflog_Id];
        BatchIF_Log__c iflog = null;
        if (iflogList.size() > 0) {
            iflog = iflogList.get(0);
            iflog.ErrorLog__c = '';
        } else {
            // データ取れってないとは、rollbackされていることです
            return;
        }
        String logstr = iflog.Log__c + ' ' + 'NumberOfRecord=' + ordIds.size() + '\n';

        // Monitoringの設定
        Datetime nowDT = Datetime.now();
        String nowStr = nowDT.format('yyyyMMddHHmm');
        GeDatas_element quotations = new GeDatas_element();
        NFMUtil.Monitoring  me = new NFMUtil.Monitoring();
        me.Tag                  = 'MSGH';
        me.Sender               = '8405';
        me.Receiver             = '1330';
        me.MessageType          = 'SBG027';
        me.MessageGroupNumber   = iflog.Name;
        me.NumberOfRecord       = '' + ordIds.size();
        me.TransmissionDateTime = nowStr;
        me.Text = '';
        quotations.Monitoring = me;
        BatchIF_Log__c rowData = null;
        try {
             //転送データを取得、参照先のデータがあるので、ここで検索必要です。Level_Category__c
            List<order> ordList = [select Id,Name,Opportunity.Name, Opportunity.CurrencyIsoCode,OrderNumber,Opportunity.ForeignTradeCompany__r.ManagementCode_F__c,CustomerContractPriceD__c,SpecialCondition_text__c,SalesChannel__c,
                                                Owner.Name,Opportunity.AccountId__c,Opportunity.InquiryNumber__c,Opportunity.SpecialDeliveryAddress__r.ManagementCode_F__c, ServiceFee_D__c,Opportunity.SpecialDeliveryAddress_D__c,Opportunity.SpecialDeliveryAddress_D__r.ManagementCode_F__c,
                                                Opportunity.ProductSegment__c, Opportunity.TradeType__c,Opportunity.Dealer__r.ManagementCode_Ext__c,EndUserD__c,ExpDelDate__c,EndUserD__r.ManagementCode_F__c,Discount_D__c,
                                                Opportunity.EndUser__c, Opportunity.Machine_Parts__c,Opportunity.Dealer__r.ManagementCode_F__c,Opportunity.Account.ManagementCode_F__c,Contract.Name,Shipment_Term_D__c,Shipment_Term2_D__c,
                                                Opportunity.SalesChannel__c, Opportunity.ExpectedDeliveryDate__c, Opportunity.DealerId__c,Opportunity.DealerSalesStaffName__c,OlympusContractPricesD__c,SpecialDeliveryContact_D__c,Opportunity.SpecialDeliveryContact_D__r.ManagementCode_F__c,
                                                Opportunity.ForeignTradeCompany__c, Opportunity.SpecialDeliveryAddress__c,PaymentTerms__c,SpecialDeliveryContact__c,PDF_Sp_Shipment_Term__c,PDF_Sp_ShippingTerms__c,
                                                ForeignTradeCompany_D__r.ManagementCode_F__c, SpecialDeliveryAccount_D__r.ManagementCode_F__c, SpecialDeliveryContact2_D__r.ManagementCode_F__c,Opportunity.Dealer__r.DummyDealer__c,ContractPriceTotal__c,
                                                If_Supervise__c,CrossCooperativeDealerCode__c,SplitRatio__c,CrossCooperativeProject__c,Level_Category__c,DealerSalesStaffNameA__c,Dealer_A__r.ManagementCode_Ext__c,Dealer_B__r.ManagementCode_F__c 
                                             from order where Id IN :ordIds ];
            //List<order> ordList = [select Id,Name,Opportunity.Name, Opportunity.CurrencyIsoCode,OrderNumber,Opportunity.ForeignTradeCompany__r.ManagementCode_F__c,CustomerContractPriceD__c,SpecialCondition_text__c,SalesChannel__c,
            //                                    Owner.Name,Opportunity.AccountId__c,Opportunity.InquiryNumber__c,Opportunity.SpecialDeliveryAddress__r.ManagementCode_F__c, ServiceFee_D__c,Opportunity.SpecialDeliveryAddress_D__c,Opportunity.SpecialDeliveryAddress_D__r.ManagementCode_F__c,
            //                                    Opportunity.ProductSegment__c, Opportunity.TradeType__c,Opportunity.Dealer__r.ManagementCode_Ext__c,EndUserD__c,ExpDelDate__c,EndUserD__r.ManagementCode_F__c,Discount_D__c,
            //                                    Opportunity.EndUser__c, Opportunity.Machine_Parts__c,Opportunity.Dealer__r.ManagementCode_F__c,Opportunity.Account.ManagementCode_F__c,Contract.Name,Shipment_Term_D__c,Shipment_Term2_D__c,
            //                                    Opportunity.SalesChannel__c, Opportunity.ExpectedDeliveryDate__c, Opportunity.DealerId__c,Opportunity.DealerSalesStaffName__c,OlympusContractPricesD__c,SpecialDeliveryContact_D__c,Opportunity.SpecialDeliveryContact_D__r.ManagementCode_F__c,
            //                                    Opportunity.ForeignTradeCompany__c, Opportunity.SpecialDeliveryAddress__c,PaymentTerms__c,SpecialDeliveryContact__c,PDF_Sp_Shipment_Term__c,PDF_Sp_ShippingTerms__c,
            //                                    ForeignTradeCompany_D__r.ManagementCode_F__c, SpecialDeliveryAccount_D__r.ManagementCode_F__c, SpecialDeliveryContact2_D__r.ManagementCode_F__c,Opportunity.Dealer__r.DummyDealer__c,ContractPriceTotal__c
            //                               from order where Id IN :ordIds ];
System.debug('111111 ordList='+ordList);
            // Quotationのデータの設定
            
            List<DecideQuoteProductSet__c> decideQuoteProductSetList = [
                                select Id,Name,DecideProductSet__c,DecideProductSetCount__c,
                                    DecideOpportunity__c,DecideProductSet__r.Code__c,
                                    DecideQuote__c,DecideOrder__c,DecideProductSet__r.Name
                                from DecideQuoteProductSet__c
                                where DecideOrder__c In :ordIds
                                ];
           
            Map<String,String> dqpsNameAndCountMap = new Map<String,String>();
            String name ; String count;
            String value; String bppMapGetValue;
            for (DecideQuoteProductSet__c dqps :decideQuoteProductSetList) {
                name = dqps.DecideProductSet__r.Code__c;
                count = String.valueOf(dqps.DecideProductSetCount__c);
                value = name +','+ count;
                if (dqpsNameAndCountMap.containsKey(dqps.DecideOrder__c)) {

                    bppMapGetValue = dqpsNameAndCountMap.get(dqps.DecideOrder__c) +';'+ value ;
                    dqpsNameAndCountMap.put(dqps.DecideOrder__c, bppMapGetValue);
                } else {
                    dqpsNameAndCountMap.put(dqps.DecideOrder__c, value);
                }
            }
            //XHL-20190510-AddEnd




            quotations.GeData = new List<GeData_element>();
            for (Order ord : ordList) { 
                // 商談商品情報を取得
                List<OrderItem> ordLiList = 
                                        [select Id, Quantity, PricebookEntry.ProductCode,QuoteLineItem.SingleProduct__c,
                                            ODISingleProduct__c,Order.ProductSegment__c
                                           from OrderItem where OrderId = :ord.Id 
                                           order by ODISingleProduct__c desc,id];


                GeData_element quotation = new GeData_element();

                //CBPR
                if(ord.Opportunity.ProductSegment__c == 'BS'){
                    if(ord.If_Supervise__c){
                        if (ord.Level_Category__c == '二类') {
                            quotation.ZNMPA = 'Y';
                        } else if(ord.Level_Category__c == '一类'){
                            quotation.ZNMPA = 'X';
                        } else {
                            quotation.ZNMPA = 'N';
                        }
                    } else {
                        quotation.ZNMPA = null;
                    }
                } else {
                    quotation.ZNMPA = null;
                }
                /*if(ord.Opportunity.ProductSegment__c == 'BS'){
                    if (ord.If_Supervise__c) {
                        quotation.ZNMPA = 'Y';
                    } else {
                        quotation.ZNMPA = 'N';
                    }
                }else{
                    quotation.ZNMPA = null;
                }*/
                
                
                //CBPR
                if (ord.Opportunity.Dealer__r.DummyDealer__c == true || ord.Opportunity.SalesChannel__c == 'direct'){
                quotation.DealerCode          = ord.Opportunity.Account.ManagementCode_F__c;
                    if (ord.Opportunity.TradeType__c == 'Tax Exemption' && ord.Opportunity.SalesChannel__c == 'direct') {
                        quotation.SalesAccountCode = ord.Opportunity.Account.ManagementCode_F__c;
                    }else {
                        quotation.SalesAccountCode = ord.SpecialDeliveryAccount_D__r.ManagementCode_F__c;
                    }
                }
                else{
                quotation.DealerCode          = ord.Opportunity.Dealer__r.ManagementCode_Ext__c;
                quotation.SalesAccountCode                   = ord.Opportunity.Account.ManagementCode_F__c;

                }
                quotations.GeData.add(quotation);
                quotation.OrderCode                      = ord.OrderNumber;
                quotation.OpportunityCode                = ord.Opportunity.InquiryNumber__c;
//                //quotation.SalesAccountCode                   = ord.Opportunity.Account.ManagementCode_F__c;
                quotation.ProductSegment              = ord.Opportunity.ProductSegment__c;
                quotation.TradeType              = ord.Opportunity.TradeType__c;
                quotation.MachineParts                   = ord.Opportunity.Machine_Parts__c;
                quotation.SalesChannel   =                 ord.Opportunity.Machine_Parts__c == 'Parts' ? '40' : ord.Opportunity.SalesChannel__c == 'dealer' ?  '41' : '42';
                quotation.DeliveryDate          = NFMUtil.formatDate2Str(ord.Opportunity.ExpectedDeliveryDate__c);
//               // quotation.DealerCode          = ord.Opportunity.Dealer__r.ManagementCode_Ext__c;
                quotation.DealerSalesStaffName         = ord.Opportunity.DealerSalesStaffName__c;
                quotation.ForeignTradeCompany                   = ord.ForeignTradeCompany_D__r.ManagementCode_F__c;
                quotation.PaymentCondition                  = ord.PaymentTerms__c;
                quotation.EndUser            =  ord.EndUserD__r.ManagementCode_F__c;
                quotation.DeliveryDate = NFMUtil.formatDate2Str(ord.ExpDelDate__c);
                quotation.ServiceFee      =  ord.ServiceFee_D__c;
                //2017/01/15追加
                if(ord.Opportunity.SalesChannel__c == 'direct' && ord.Opportunity.Machine_Parts__c == 'Parts'){
                     quotation.Discount         = 0;
                     quotation.OlympusContractPrices = ord.CustomerContractPriceD__c;
                }
                else{
                    quotation.Discount         = ord.Discount_D__c;
                    quotation.OlympusContractPrices = ord.ContractPriceTotal__c;
                }
                quotation.SpecialDeliveryAddress                   = ord.SpecialDeliveryAccount_D__r.ManagementCode_F__c + ',' + ord.SpecialDeliveryContact2_D__r.ManagementCode_F__c;
                //quotation.Other1            = ord.Name + ',' + ord.SalesChannel__c;

                String  other1 = ord.Name + ',' + ord.SalesChannel__c;
                if (String.isNotBlank(other1) && other1.indexof('%') != -1) {
                    other1 = other1.replace('%','％');
                }
                quotation.Other1 = other1;
                
                String other2 = ord.SpecialCondition_text__c;
                if (String.isNotBlank(other2) && other2.indexof('%') != -1) {
                    other2 = other2.replace('%','％');
                }
                quotation.Other2            = other2;//ord.SpecialCondition_text__c;
                quotation.Other3            = ord.Shipment_Term_D__c + ',' + ord.Shipment_Term2_D__c;
                // 跨区域销售 XHL 20210831 Start
                /*quotation.CoopAgent = '';
                quotation.CoopAgentPCT = '';
                if (ord.CrossCooperativeProject__c) {//跨省份合作项目
                    quotation.CoopAgent = ord.Dealer_B__r.ManagementCode_F__c;//合作区域代理商Code
                    quotation.DealerCode         = ord.Dealer_A__r.ManagementCode_Ext__c;
                    quotation.DealerSalesStaffName = ord.DealerSalesStaffNameA__c;
                    String splitRatio = ord.SplitRatio__c;
                    if (String.isNotBlank(splitRatio) && splitRatio.indexof(':') > 0) {
                        Integer pct = Integer.valueOf(splitRatio.split(':')[1].trim())*10;
                        quotation.CoopAgentPCT = String.valueof(pct);//业绩拆分比例(取:后边的值*10)
                    } 
                } */

                quotation.CoopAgent = '';
                quotation.CoopAgentPCT = '';
                if (ord.CrossCooperativeProject__c) {//跨省份合作项目
                    quotation.CoopAgent = ord.CrossCooperativeDealerCode__c;//合作区域代理商Code
                    String splitRatio = ord.SplitRatio__c;
                    if (String.isNotBlank(splitRatio) && splitRatio.indexof(':') > 0) {
                        Integer pct = Integer.valueOf(splitRatio.split(':')[1].trim())*10;
                        quotation.CoopAgentPCT = String.valueof(pct);//业绩拆分比例(取:后边的值*10)
                    } 
                } 
                // 跨区域销售 XHL 20210831 End
                quotation.GeDataDetails = new List<GeDataDetails_element>();
                //Detail_element
                Integer m = 0;
                for (Integer i = 0; i < ordLiList.size(); i++) {
                    
                    if (ordLiList.get(i).Order.ProductSegment__c == 'BS') {

                        //XHL-20190510-AddStart
                        if (!ordLiList.get(i).ODISingleProduct__c) {
                            continue;
                        }
                        m++;
                        //XHL-20190510-AddEnd
                        GeDataDetails_element detail = new GeDataDetails_element();
                        quotation.GeDataDetails.add(detail);
                        detail.DetailLine                  = (i + 1) * 10;
                        detail.ItemCode                    = ordLiList.get(i).PricebookEntry.ProductCode;
                        detail.ItemQuantity                = Integer.valueOf(ordLiList.get(i).Quantity);
                    } else {

                        GeDataDetails_element detail = new GeDataDetails_element();
                        quotation.GeDataDetails.add(detail);
                        detail.DetailLine                  = (i + 1) * 10;
                        detail.ItemCode                    = ordLiList.get(i).PricebookEntry.ProductCode;
                        detail.ItemQuantity                = Integer.valueOf(ordLiList.get(i).Quantity);
                    }
                    
                }

                //XHL-20190510-AddStart
                if (dqpsNameAndCountMap.containsKey(ord.Id)) {
                    value = dqpsNameAndCountMap.get(ord.Id);
                    List<String> nameCountList = new List<String>();
                    for (String str: value.split(';')){
                        nameCountList.add(str);
                    }
                    if (nameCountList.size() > 0 ){

                        for (String  nameCount :nameCountList) {

                            GeDataDetails_element detail = new GeDataDetails_element();
                            quotation.GeDataDetails.add(detail);
                            detail.DetailLine                  = (m + 1) * 10;
                            detail.ItemCode                    = nameCount.split(',')[0];
                            detail.ItemQuantity                = Integer.valueOf(nameCount.split(',')[1]);
                            m++;
                        }
                    }

                }
                //XHL-20190510-AddEnd
                logstr += quotation.OrderCode + '\n';
            }

            if (quotations.GeData.size() > 0) {
                //SBG027Sync.Quotations_element[] pQuotations = new SBG027Sync.Quotations_element[] { quotations };
                logstr += '\ncallout count=' + quotations.GeData.size();
                //OlympusCoJpCommonMessage.LOG_element[] logs = stub.SBG027_Sync_BC2GPI(pQuotations);
                // 原則非同期ですので、logsを確認する必要がないでしょう。
                NFMUtil.Monitoring Monitoring   = new NFMUtil.Monitoring();
                Monitoring.Tag                  = quotations.Monitoring.Tag;
                Monitoring.Sender               = quotations.Monitoring.Sender;
                Monitoring.Receiver             = quotations.Monitoring.Receiver;
                Monitoring.MessageType          = quotations.Monitoring.MessageType;
                Monitoring.MessageGroupNumber   = quotations.Monitoring.MessageGroupNumber;
                Monitoring.NumberOfRecord       = quotations.Monitoring.NumberOfRecord;
                Monitoring.TransmissionDateTime = quotations.Monitoring.TransmissionDateTime;
                Monitoring.Text = '';
                SBG027 sBG027 = new SBG027();
                sBG027.GeDatas =  quotations;
                rowData = NFMUtil.makeRowData(Monitoring, 'SBG027', sBG027);
                execute(rowData, iflog);
            }
            Set<String> inquiryNoList = new Set<String>();

            Map<String, Order> ordUpsertMap = new Map<String, Order>();
            logstr += '\nend';
        } catch(Exception ex) {
            // エラーが発生した場合
            System.debug(Logginglevel.ERROR, 'SBG027_' + iflog.Name + ':' + ex.getMessage());
            System.debug(Logginglevel.ERROR, 'SBG027_' + iflog.Name + ':' + ex.getStackTraceString());
            logstr += ex.getMessage();
            iflog.ErrorLog__c += ex.getMessage() + '\n';
            iflog.ErrorLog__c += ex.getStackTraceString() + '\n';
        }
        if (rowData != null) {
            insert rowData;
        }

        System.debug(Logginglevel.DEBUG, 'SBG027_' + iflog.Name + ' end');
        iflog.Log__c = logstr;
        update iflog; 
    } 

    public static void execute2(String rowDataId) {
        List<BatchIF_Log__c> row = [select id, name, MessageGroupNumber__c, retry_cnt__c,
                                           RowDataFlg__c, ErrorLog__c, Type__c,
                                           Log__c, Log2__c, Log3__c, Log4__c, Log5__c, Log6__c,
                                           Log7__c, Log8__c, Log9__c, Log10__c, Log11__c, Log12__c
                                      from BatchIF_Log__c
                                     where id = :rowDataId];
        if (row.size() > 0) execute(row[0], null);
    }

    public static void execute(BatchIF_Log__c rowData, BatchIF_Log__c iflog) {
        //gaozw
        Integer batch_retry_max_cnt = Integer.valueOf(System.Label.batch_retry_max_cnt);
        String rowDataStr = NFMUtil.getRowDataStr(rowData);
        SBG027 sBG027 = (SBG027) JSON.deserialize(rowDataStr, SBG027.class);

        String logstr = sBG027.GeDatas.Monitoring.MessageGroupNumber + ' start\n';
        Boolean needUpdateIflog = false;
        if  (iflog == null) {
            needUpdateIflog = true;
            iflog = new BatchIF_Log__c();
            iflog.Type__c = 'SBG027';
            iflog.MessageGroupNumber__c = sBG027.GeDatas.Monitoring.MessageGroupNumber;
            iflog.Log__c = logstr;
            iflog.ErrorLog__c = '';
            //insert iflog;
            //iflog = [Select Id, Name, Log__c, ErrorLog__c from BatchIF_Log__c where Id = :iflog.Id];
        } else {
            logstr = iflog.Log__c;
        } 
        try{
            
            NFMUtil.sendToSap(rowDataStr, NFMUtil.SBG027_ENDPOINT); 
            rowData.retry_cnt__c = 0;
        }catch(Exception ex) {
            // TODO IOException
            // エラーが発生した場合
            System.debug(Logginglevel.ERROR, 'SBG027_' + iflog.Name + ':' + ex.getMessage());
            System.debug(Logginglevel.ERROR, 'SBG027_' + iflog.Name + ':' + ex.getStackTraceString());
            logstr += ex.getMessage();
            iflog.ErrorLog__c += ex.getMessage() + '\n';
            iflog.ErrorLog__c += ex.getStackTraceString() + '\n';

            //---xiongyl---add
            if (rowData.retry_cnt__c == null) rowData.retry_cnt__c = 0;
            if (rowData.retry_cnt__c < batch_retry_max_cnt){
                rowData.retry_cnt__c++;
                //---20200309→XHL→Add→Start
                LogAutoSendSchedule.assignOneMinute();
                //---20200309→XHL→Add→End
            }
            if (rowData.retry_cnt__c >= batch_retry_max_cnt){
                rowData.ErrorLog__c = ex.getMessage() + '\n' + ex.getStackTraceString() + '\n' + rowData.ErrorLog__c+'错误次数已经超过自动送信设定的最大次数，请手动送信';
            }
        }
        iflog.Log__c = logstr;
        if (needUpdateIflog) {
            upsert iflog;
            update rowData;
        }
    }


}