public with sharing class NFM009Controller {
    //CHAN-BSV3GZ SAP返回状态值 start
    public static String status;
    // CHAN-BSV3GZ end

    public class DataBean {
        public NFMUtil.Monitoring Monitoring;
        public Forecast_element[] Forecast;
    }

    public class Forecast_element {

        public String QuotationCode;
        public String SalesPoint;
        public String ProspectCategory;
        public String SalesChannel;
        public String Agent1Code;
        public String EnduserCode;
        public String DepartmentCode;
        public String Currency_x;
        public String ForecastDate;
        public String SalesPersonCode;
        public String SalesPersonName;
        public String QuotationLevel;
        public String CLBICCategory;
        public String Other1;
        public Detail_element[] Detail;
        public PresalesPerson_element[] PresalesPerson;
    }

    public class Detail_element {
        public String ItemCode;
        public String ItemQuantity;
    }

    public class PresalesPerson_element{
        public String PresalesPersonCode;
        public String PresalesPersonName;
    }
    //@future (callout=true)
    //public static void calloutFuture(String iflog_Id,List<String> oppIds){
    //    callout(iflog_Id,oppIds);
    //}
    //xinhonglu
    public static void callout(BatchIF_Log__c iflog, List<String> oppIds){
    //public static void callout(String iflog_Id, List<String> oppIds){
        if (oppIds == null || oppIds.size() == 0) {
            return;
        }
        //insert iflog;
        //if(iflog == null){
        //    return;
        //}

         // 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=' + oppIds.size() +'\n';

        DataBean db = new DataBean();
        NFMUtil.Monitoring me = new NFMUtil.Monitoring();
        Datetime nowDT = Datetime.now();
        String nowStr = nowDT.format('yyyyMMddHHmm');

        me.Tag                  = 'MSGH';
        me.Sender               = 'SFDC';
        me.Receiver             = 'SAP';
        me.MessageType          = 'SFDC002';
        me.MessageGroupNumber   = iflog.Name;
        me.NumberOfRecord       = '' + oppIds.size();
        me.TransmissionDateTime = nowStr;
        me.Text = '';
        db.Monitoring = me;
        BatchIF_Log__c rowData = null;
        // BatchIF転送表 から、コード変換のMapを作成
        Map<String, String> transferMap = new Map<String, String>();
        List<BatchIF_Transfer__c> transferList = [select Table__c,
                                                         Column__c,
                                                         External_value__c,
                                                         Internal_value__c
                                                    from BatchIF_Transfer__c
                                                   where Dropped_Flag__c = false
                                                     and Table__c = 'Opportunity'];
        for (BatchIF_Transfer__c t : transferList) {
            transferMap.put(t.Column__c + t.Internal_value__c, t.External_value__c);
        }

        try{
            // 転送データを取得、参照先のデータがあるので、ここで検索必要です。
            List<Opportunity> oppList = [select Id, Name, 
                                                CurrencyIsoCode,
                                                Owner.Name, 
                                                Owner.Employee_No__c,
                                                Opportunity_No__c, 
                                                SalesPoint_Code__c,
                                                Account.AgencyContract_Management_Code__c,
                                                Sales_Root__c,
                                                Opportunity_Category__c,
                                                Agency1__r.Management_Code__c,
                                                Purchase_Type__c, 
                                                Competitor__c,
                                                Close_Forecasted_Date__c,
                                                CloseDate,
                                                Hospital__c, Hospital__r.Management_Code__c,
                                                Account.Id, Account.Management_Code__c,  Account.RecordType.DeveloperName,
                                                Account.Name, Account.ParentId, Account.Parent.Management_Code__c,
                                                OCM_Agent1_Price__c,
                                                Agency1__c, 
                                                Agency2__c, Agency2__r.Management_Code__c,
                                                Promise_Class__c, Fund_Basis__c,
                                                Authorized_DB_No__c, NotesApprovedNo__c, Sales_Contract_No__c,
                                                Salesdepartment_Owner__c, 
                                                STMS_Package_Sale__c, Equipment_Order_Flg__c
                                           from Opportunity where Id IN :oppIds];
            System.debug(Logginglevel.DEBUG, 'NFM009_ oppList.size()=' + oppList.size());
            System.debug(Logginglevel.DEBUG, 'Opportunity++++1' + oppList.get(0));
            
            // Forecastのデータの設定
            
            db.Forecast = new List<Forecast_element>();
            List<String> oppIdList = new List<String>();
            for(Opportunity opp : oppList){
                oppIdList.add(opp.Id);
            }

            // 商談商品情報を取得
            List<OpportunityLineItem> oppLiList = 
                                        [select Id, Quantity, PricebookEntry.ProductCode, OpportunityId, Opportunity.Opportunity_No__c,
                                             Item_Order__c,ListPrice__c,UnitPrice__c,
                                             //CHAN-BX66KN add 2021-01-14 by gwy start 
                                             PricebookEntry.Product2.SFDA_Status__c,PricebookEntry.Product2.Correspond_Code__r.SFDA_Status__c,
                                             PricebookEntry.Product2.SFDA_Approbated_Status__c,PricebookEntry.Product2.Correspond_Code__c
                                             ,PricebookEntry.Product2.Correspond_ProductCode__c
                                             //CHAN-BX66KN add 2021-01-14 by gwy end
                                           from OpportunityLineItem where Opportunity.Id = :oppIdList];
            // チームメンバー
            List<OpportunityTeamMember> oppTMList = 
                                        [select Id, User.Employee_No__c, User.Name, OpportunityId, Opportunity.Opportunity_No__c
                                           from OpportunityTeamMember where OpportunityId in :oppIdList]; 

            Map<String,List<OpportunityLineItem>> oppTZMap = new Map<String,List<OpportunityLineItem>>();
            Map<String,List<OpportunityLineItem>> oppLiMap = new Map<String,List<OpportunityLineItem>>();
            Map<String,List<OpportunityTeamMember>> oppTMMap = new Map<String,List<OpportunityTeamMember>>();
            for(OpportunityLineItem oli:oppLiList){
                if(oppLiMap.containsKey(oli.Opportunity.Opportunity_No__c)){
                    oppLiMap.get(oli.Opportunity.Opportunity_No__c).add(oli);
                }else {
                    List<OpportunityLineItem> oliList = new List<OpportunityLineItem>();
                    oliList.add(oli);
                    oppLiMap.put(oli.Opportunity.Opportunity_No__c,oliList); 
                }
                //gwy 2021-01-14
                if((oli.PricebookEntry.Product2.SFDA_Status__c == '停止' && oli.PricebookEntry.Product2.Correspond_Code__r.SFDA_Status__c == '停止') ||
                   (oli.PricebookEntry.Product2.SFDA_Status__c == '停止' && String.isBlank(oli.PricebookEntry.Product2.Correspond_Code__c))){
                   if(oppTZMap.containsKey(oli.Opportunity.Opportunity_No__c)){
                        oppTZMap.get(oli.Opportunity.Opportunity_No__c).add(oli);
                    }else {
                        List<OpportunityLineItem> otzList = new List<OpportunityLineItem>();
                        otzList.add(oli);
                        oppTZMap.put(oli.Opportunity.Opportunity_No__c,otzList);
                    }      
                }
                    
            }
            

            for(OpportunityTeamMember otm:oppTMList){
                if(oppTMMap.containsKey(otm.Opportunity.Opportunity_No__c)){
                    oppTMMap.get(otm.Opportunity.Opportunity_No__c).add(otm);
                } else {
                    List<OpportunityTeamMember> otmList = new List<OpportunityTeamMember>();
                    otmList.add(otm);
                    oppTMMap.put(otm.Opportunity.Opportunity_No__c,otmList);
                }
            }
            
            for(Opportunity opp : oppList){
                //gwy 2021-01-14
                if(oppTZMap.containsKey(opp.Opportunity_No__c)){
                   iflog.ErrorLog__c='Error! QuotationCode[' +opp.Opportunity_No__c+ '] contain inactive product. This DN is skipped.\n'; 
                   continue;
                }
                
                Forecast_element fe = new Forecast_element();
                db.Forecast.add(fe);
                fe.QuotationCode                = opp.Opportunity_No__c;
                fe.SalesPoint                   = opp.SalesPoint_Code__c;
                fe.SalesPersonCode              = opp.Owner.Employee_No__c;
                fe.SalesPersonName              = opp.Owner.Name;
                fe.Currency_x                   = opp.CurrencyIsoCode; 
                
                System.debug(Logginglevel.ERROR, 'NFM009_Account RecordType:' + opp.Account.RecordType.DeveloperName);
                if (opp.Account.RecordType.DeveloperName == 'AgencyContract') {
                    // 合同编码
                    fe.EnduserCode                  = opp.Account.AgencyContract_Management_Code__c;
                    fe.DepartmentCode               = opp.Account.AgencyContract_Management_Code__c;
                System.debug(Logginglevel.ERROR, 'NFM009_AgencyContract EnduserCode:' + fe.EnduserCode);
                System.debug(Logginglevel.ERROR, 'NFM009_AgencyContract DepartmentCode:' + fe.DepartmentCode);
                } else {
                    fe.EnduserCode                  = opp.Hospital__r.Management_Code__c;
                    fe.DepartmentCode               = opp.Account.Management_Code__c;
                System.debug(Logginglevel.ERROR, 'NFM009_Hospital EnduserCode:' + fe.EnduserCode);
                System.debug(Logginglevel.ERROR, 'NFM009_Hospital DepartmentCode:' + fe.DepartmentCode);
                }
       
                fe.SalesChannel                 = NFMUtil.getMapValue(transferMap, 'Sales_Root__c', opp.Sales_Root__c, iflog);
                //20190107
                if(opp.Sales_Root__c == '販売店' && String.isBlank(opp.Agency1__c)){
                    fe.Agent1Code                   = opp.Hospital__r.Management_Code__c;
                } else {
                    fe.Agent1Code                   = opp.Agency1__r.Management_Code__c;
                }

                fe.CLBICCategory                = NFMUtil.getMapValue(transferMap, 'Opportunity_Category__c', opp.Opportunity_Category__c, iflog);
                fe.ProspectCategory             = NFMUtil.getMapValue(transferMap, 'Purchase_Type__c', opp.Purchase_Type__c, iflog);
                fe.ForecastDate                 = NFMUtil.formatDate2Str(opp.CloseDate);
                fe.QuotationLevel               = opp.Competitor__c;
                fe.Other1                       = NFMUtil.getMapValue(transferMap, 'Salesdepartment_Owner__c', opp.Salesdepartment_Owner__c, iflog);
                fe.Detail = new List<Detail_element>(); 
                
                if(oppLiMap.get(opp.Opportunity_No__c) != null){
                    for (Integer i = 0; i < oppLiMap.get(opp.Opportunity_No__c).size(); i++) {
                        Detail_element de = new Detail_element();
                        fe.Detail.add(de);
                //CHAN-BX66KN update by gwy 2021-02-07 start      
                        de.ItemCode                    = 
                        oppLiMap.get(opp.Opportunity_No__c).get(i).PricebookEntry.Product2.Correspond_Code__c == null ?
                        oppLiMap.get(opp.Opportunity_No__c).get(i).PricebookEntry.ProductCode:
                        oppLiMap.get(opp.Opportunity_No__c).get(i).PricebookEntry.Product2.Correspond_ProductCode__c;
                //CHAN-BX66KN update by gwy 2021-02-07 end
                        de.ItemQuantity                = String.valueOf(oppLiMap.get(opp.Opportunity_No__c).get(i).Quantity);
                    }
                }                         
                    
                fe.PresalesPerson = new List<PresalesPerson_element>();
                if(oppTMMap.get(opp.Opportunity_No__c) != null){
                    for (Integer i = 0; i < oppTMMap.get(opp.Opportunity_No__c).size(); i++) {
                       PresalesPerson_element pe = new PresalesPerson_element();
                        fe.PresalesPerson.add(pe);
                        pe.PresalesPersonCode          = oppTMMap.get(opp.Opportunity_No__c).get(i).User.Employee_No__c;
                        pe.PresalesPersonName          = oppTMMap.get(opp.Opportunity_No__c).get(i).User.Name;
                    }
                }
                system.debug('fe.PresalesPerson' + fe.PresalesPerson);
                if(oppLiMap.get(opp.Opportunity_No__c) != null && oppTMMap.get(opp.Opportunity_No__c) != null){
                    logstr += fe.QuotationCode + 'Detail[' + oppLiMap.get(opp.Opportunity_No__c).size() + ']PresalesPerson[' + oppTMMap.get(opp.Opportunity_No__c).size() + '] ';
                } 
            }
                

            if (db.Forecast.size() > 0) {
                
                logstr += '\ncallout count=' + db.Forecast.size();
                // 原則非同期ですので、logsを確認する必要がないでしょう。
                NFMUtil.Monitoring Monitoring   = new NFMUtil.Monitoring();
                Monitoring.Tag                  = db.Monitoring.Tag;
                Monitoring.Sender               = db.Monitoring.Sender;
                Monitoring.Receiver             = db.Monitoring.Receiver;
                Monitoring.MessageType          = db.Monitoring.MessageType;
                Monitoring.MessageGroupNumber   = db.Monitoring.MessageGroupNumber;
                Monitoring.NumberOfRecord       = db.Monitoring.NumberOfRecord;
                Monitoring.TransmissionDateTime = db.Monitoring.TransmissionDateTime;
                Monitoring.Text = '';


                rowData = NFMUtil.makeRowData(Monitoring, 'NFM009', db);
                System.debug('+++++rowData+++++' + rowData);
                execute(rowData, iflog);
            }
            // CHAN-BSV3GZ start
            // 保存 status 状态
            logstr += '\nStatus:' + status;
            //CHAN-BSV3GZ end
            logstr += '\nend';

            if(System.Test.isRunningTest()){
                Opportunity opportunityInfos = null;
                update opportunityInfos;

            }
        } catch(Exception ex) {

            // エラーが発生した場合
            System.debug(Logginglevel.ERROR, 'NFM009_' + iflog.Name + ':' + ex.getMessage());
            System.debug(Logginglevel.ERROR, 'NFM009_' + 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, 'NFM009_' + iflog.Name + ' end');
        iflog.Log__c = logstr;
        //update iflog;
        //insert iflog;
        upsert 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) {
        //xinhonglu
        Integer batch_retry_max_cnt = Integer.valueOf(System.Label.batch_retry_max_cnt);
        String rowDataStr = NFMUtil.getRowDataStr(rowData);
        System.debug('+++11111111--rowData--111111111111+++++(' + rowData+')');

        DataBean db = (DataBean) JSON.deserialize(rowDataStr, DataBean.class);

        String logstr = db.Monitoring.MessageGroupNumber + ' start\n';
        Boolean needUpdateIflog = false;
        if  (iflog == null) {
            needUpdateIflog = true;
            iflog = new BatchIF_Log__c();
            iflog.Type__c = 'NFM009';
            iflog.MessageGroupNumber__c = db.Monitoring.MessageGroupNumber;
            iflog.Log__c = logstr;
            iflog.ErrorLog__c = '';
            
        } else {
            logstr = iflog.Log__c;
        }

        try{
            // CHAN-BSV3GZ start
            // 原逻辑
            //NFMUtil.sendToSap(rowDataStr, NFMUtil.NFM009_ENDPOINT); 
            // 接收 SAP返回状态
            status =
             NFMUtil.sendToSapRet(rowDataStr, NFMUtil.NFM009_ENDPOINT);
            // CHAN-BSV3GZ end


            logstr += '\nstatus:' +  status;
            // CHAN-BSV3GZ start
            // 原代码
            // rowData.retry_cnt__c=0;
            if (status == 'OK') {
                rowData.retry_cnt__c = 0;
            } else {
                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 = 'status:' + status +
                                          '\n错误次数已经超过自动送信设定的最大次数，请手动送信';
                }
            }
            // CHAN-BSV3GZ end
        }catch(Exception ex) {
            // TODO IOException
            // エラーが発生した場合
            System.debug(Logginglevel.ERROR, 'NFM009_' + iflog.Name + ':' + ex.getMessage());
            System.debug(Logginglevel.ERROR, 'NFM009_' + iflog.Name + ':' + ex.getStackTraceString());
            logstr += ex.getMessage();
            iflog.ErrorLog__c += ex.getMessage() + '\n';
            iflog.ErrorLog__c += ex.getStackTraceString() + '\n';

           
            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+'错误次数已经超过自动送信设定的最大次数，请手动送信';
            }
        }

        
        iflog.Log__c = logstr;
        if (needUpdateIflog) {
            insert iflog;
            update rowData;
        }
    }
}