/**
 * 调用地址
 * UpdateContractAimAmountHandler.SetAwaitToSendAWS
 */
public without sharing class NFM601Controller {
    public static String logstr = '';
    public static String status;
    private static final String LOG_TYPE = 'NFM601';
    public class NFM601 {
        public GeDatas GeDatas;
    }
    public class GeDatas {
        public NFMUtil.MonitoringToComPlat Monitoring;
        public GeData[] GeData;
    }
    public class GeData {
        public String ManageCode; //管理编码 SFDC的管理编码（医院/科室/经销商
        public String ManageCode2; //智慧医疗编码 标识为经销商时，本字段不需要传输；SFDC新建医院或科室时本字段值为空；
        public String Name; //名称
        public String Identification; //标识 1:医院；2：科室；3：经销商
        public String SalesBusinessDivision; //销售本部
        public String State; //省(文本)
        public String City; //市
        public Boolean Status; //状态
        // 医院
        public String Alias1; //别名1
        public String Alias2; //别名2
        public String Abbreviation; //简称 （SFDC需新加字段）
        public String Phone; //电话
        public String ZIPCode; //邮编
        public String Address; //地址
        public String OCSMCategory; //OCSM分类
        public String HospitalLevel; //政府等级
        // 科室
        public String DepartmentClass; //科室类别
        public String HospitalCode; //关联医院
        // 经销商
        public String QuolifiedValidityDate; //三证资质最早有效期
        public String ContractEndDate; //最晚合同有效期
    }



    //正常调用
    @future(callout = true)
    public static void callout(String iflog_Id, List < String > accountIdList) {
        executefuture(iflog_Id, accountIdList);
    }
    //Batch调用
    public static void executefuture(String iflog_Id, List < String > accountIdList) {
        BatchIF_Log__c iflog = null;
        Datetime nowDT = Datetime.now();
        String nowStr = nowDT.format('yyyyMMddHHmmss');

        if (String.isNotBlank(iflog_Id)) {
            List < BatchIF_Log__c > iflogList = [Select Id, Name, Log__c, ErrorLog__c from BatchIF_Log__c where Id =: iflog_Id];
            if (iflogList.size() > 0) {
                iflog = iflogList.get(0);
                iflog.ErrorLog__c = '';
            } else {
                iflog = new BatchIF_Log__c();
                iflog.MessageGroupNumber__c = nowStr;
            }
        } else {
            iflog = new BatchIF_Log__c();
            iflog.MessageGroupNumber__c = nowStr;
        }


        NFMUtil.MonitoringToComPlat me = new NFMUtil.MonitoringToComPlat();
        me.Tag = 'MSGH';
        me.Sender = 'SFDC';
        me.Receiver = '智慧医疗/服务新系统';
        me.MessageType = LOG_TYPE;
        me.MessageGroupNumber = nowStr; //iflog.Name;
        if (String.isNotBlank(iflog.Name)) {
            me.MessageGroupNumber = iflog.Name;
        }
        // me.NumberOfRecord       = '' + qisIds.size();
        me.TransmissionDateTime = nowStr;
        me.Text = '';
        String randomstr = NFMUtil.randomUUID(16);
        Long timestamp = DateTime.now().getTime();
        String timestampStr = String.valueOf(timestamp);
        String getToken = NFMUtil.getToken(randomstr, timestamp);
        me.API_RANDOM_STR = randomstr;
        me.API_TIME = timestampStr;
        me.API_TOKEN = getToken;
        me.sign = NFMUtil.getSignMD5();
        me.timestamp = timestampStr;
        me.appKey = NFMUtil.appKeyLMS;



        BatchIF_Log__c rowData = null;

        //省
        List < Address_Level__c > address_LevelList = [select Id, Name, Level1_Code__c from Address_Level__c];
        Map < String, Address_Level__c > regionNameMap = new Map < String, Address_Level__c > ();
        for (Address_Level__c level1: address_LevelList) {
            regionNameMap.put(level1.Id, level1);
        }
        //市
        List < Address_Level2__c > address_Level2List = [select Id, Name, Level2_Code__c from Address_Level2__c];
        Map < String, Address_Level2__c > cityMap = new Map < String, Address_Level2__c > ();
        for (Address_Level2__c level2: address_Level2List) {
            cityMap.put(level2.Id, level2);
        }
        List < Account > accountList =
            [
                SELECT Id,
                Name, //名称
                Department_Name__c,
                Parent.Name, 
                Management_Code__c, //管理编码
                Salesdepartment_HP__c, //销售本部(医院)
                Salesdepartment_Dept__c, //销售本部(科室)
                Salesdepartment_DeptClass__c, //销售本部(科室分类)
                State_Master__c, //省
                State_Master__r.Name, //
                State_Master__r.Level1_Code__c, //
                City_Master__c, //市
                City_Master__r.Name, //
                City_Master__r.Level2_Code__c, //
                Is_Active_Formula__c, //有效/无效（公式）
                Address__c, //地址
                OCM_Category__c, //OCSM分类(医院)
                Phone, //电话
                RecordType_DeveloperName__c, //客户记录类型_DeveloperName
                Site, //别名1
                Alias_Name2__c, //别名2
                Ban_On_Use_Date__c, //禁用日期
                Ban_On_Use_DateDD__c, //DD有效期至
                Postal_Code__c, //邮政编码
                RecordType.Name, //记录类型名称
                RecordTypeId, //记录类型Id
                Department_RecordType_Name__c, //科室分类名   
                Parent.Parent.Management_Code__c, //医院的 管理编码
                Grade__c, //政府等级
                PlatformCode__c, //智慧医疗编码
                Abbreviation__c, //简称
                Parent.Parent.State_Master__r.Level1_Code__c,
                Parent.Parent.City_Master__r.Level2_Code__c,
                Parent.ParentId, //医院Id
                Parent.Parent.RecordTypeId //记录类型
                FROM Account
                WHERE(Id IN: accountIdList OR Parent.ParentId IN: accountIdList)
                AND RecordTypeId != '01210000000QjCNAA0'
                AND(Is_Active_Formula__c = '有效'
                    OR Is_Active_Formula__c = '无效')
                ORDER BY Parent.ParentId, ParentId, Id
            ];
        //数据拼装
        GeDatas gds = new GeDatas();
        gds.GeData = new List < GeData > ();
        iflog.Log__c= iflog.Log__c == null? '':iflog.Log__c;
        try {
            // 获取经销商Id
            Set < Id > agencySet = new Set < Id > ();
            Map < Id, String > getLicenceEarliestMap = new Map < Id, String > ();
            Map < Id, String > getAgencyContractLatestMap = new Map < Id, String > ();
            for (Account acc: accountList) {
                if ('01210000000Qem1AAC'.equals(acc.RecordTypeId)) {
                    agencySet.add(acc.Id);
                }
            }
            if (agencySet.size() > 0) {
                //查找 三证资质最早有效期(经销商)
                getLicenceEarliestMap = getLicenceEarliestDate(agencySet);
                //查找 最晚合同有效期（契约）（经销商）
                getAgencyContractLatestMap = getAgencyContractLatestDate(agencySet);
            }
            for (Account acc: accountList) {
                String level1_Code = acc.State_Master__r.Level1_Code__c;
                String level2_Code = acc.City_Master__r.Level2_Code__c;
                if (String.isNotBlank(acc.Parent.ParentId)) {
                    level1_Code = acc.Parent.Parent.State_Master__r.Level1_Code__c;
                    level2_Code = acc.Parent.Parent.City_Master__r.Level2_Code__c;
                }


                GeData gd = new GeData();

                gd.ManageCode = acc.Management_Code__c; //管理编码 SFDC的管理编码（医院/科室/经销商)
                gd.ManageCode2 = ''; //智慧医疗编码 标识为经销商时，本字段不需要传输；SFDC新建医院或科室时本字段值为空；

                gd.Name = acc.Name; //名称
                gd.Identification = ''; //标识 1:医院；2：科室；3：经销商
                gd.SalesBusinessDivision = ''; //销售本部(经销商没有)
                gd.State = String.isBlank(level1_Code) ? '' : level1_Code; //省(文本)
                gd.City = String.isBlank(level2_Code) ? '' : level2_Code; //市
                gd.Status = '有效'.equals(acc.Is_Active_Formula__c) ? true : false; //状态

                // 医院
                gd.Alias1 = ''; //别名1
                gd.Alias2 = ''; //别名2
                gd.Abbreviation = ''; //简称 （SFDC需新加字段）
                gd.Phone = ''; //电话
                gd.ZIPCode = ''; //邮编
                gd.Address = ''; //地址
                gd.OCSMCategory = ''; //OCSM分类
                gd.HospitalLevel = ''; //政府等级
                // 科室
                gd.DepartmentClass = ''; //科室类别
                gd.HospitalCode = ''; //关联医院

                // 经销商
                gd.QuolifiedValidityDate = ''; //三证资质最早有效期
                gd.ContractEndDate = ''; //最晚合同有效期


                String manageCode2 = String.isBlank(acc.PlatformCode__c) ? '' : acc.PlatformCode__c; //智慧医疗编码
                // 医院
                if ('01210000000QemGAAS'.equals(acc.RecordTypeId)) {
                    iflog.Log__c += '医院 ManageCode [ ' +gd.ManageCode + ' ]\n';
                    
                    gd.Identification = '1';
                    gd.SalesBusinessDivision = acc.Salesdepartment_HP__c; //销售本部(医院)
                    gd.Alias1 = String.isBlank(acc.Site) ? '' : acc.Site; //别名1
                    gd.Alias2 = String.isBlank(acc.Alias_Name2__c) ? '' : acc.Alias_Name2__c; //别名2
                    gd.Abbreviation = String.isBlank(acc.Abbreviation__c) ? '' : acc.Abbreviation__c; //简称
                    gd.Phone = String.isBlank(acc.Phone) ? '' : acc.Phone; //电话
                    gd.ZIPCode = String.isBlank(acc.Postal_Code__c) ? '000000' : acc.Postal_Code__c; //邮编
                    gd.Address = String.isBlank(acc.Address__c) ? '' : acc.Address__c; //地址
                    gd.ManageCode2 = manageCode2; //智慧医疗编码
                    gd.OCSMCategory = acc.OCM_Category__c; //OCSM分类(医院)
                    gd.HospitalLevel = acc.Grade__c; //政府等级
                }

                // 经销商
                if ('01210000000Qem1AAC'.equals(acc.RecordTypeId)) {
                    iflog.Log__c += '经销商 ManageCode [ ' +gd.ManageCode + ' ]\n';

                    gd.Identification = '3';
                    String quolifiedValidityDate = getLicenceEarliestMap.get(acc.Id) == null ? '00000000' : getLicenceEarliestMap.get(acc.Id);
                    gd.QuolifiedValidityDate = quolifiedValidityDate; //三证资质最早有效期
                    String contractEndDate = getAgencyContractLatestMap.get(acc.Id) == null ? '00000000' : getAgencyContractLatestMap.get(acc.Id);
                    gd.ContractEndDate = contractEndDate; //最晚合同有效期
                }
                // 科室
                if ('01210000000QemGAAS'.equals(acc.Parent.Parent.RecordTypeId)) {
                    iflog.Log__c += '科室 ManageCode [ ' +gd.ManageCode + ' ]\n';
                    
                    gd.Name = acc.Parent.Name +' ' +acc.Department_Name__c;

                    gd.DepartmentClass = ''; //科室类别
                    String departmentClass = acc.Department_RecordType_Name__c;
                    if (String.isNotBlank(departmentClass) && departmentClass.contains('.')) {
                        gd.DepartmentClass = departmentClass.substring(2, departmentClass.length());
                    }
                    gd.Identification = '2';
                    gd.SalesBusinessDivision = acc.Salesdepartment_Dept__c; //销售本部(科室)
                    gd.HospitalCode = acc.Parent.Parent.Management_Code__c; //关联医院
                    gd.ManageCode2 = manageCode2; //智慧医疗编码
                }

                if (String.isNotBlank(gd.Identification)) {
                    gds.GeData.add(gd);
                }
            }

            if (gds.GeData.size() > 0) {
                me.NumberOfRecord = '' + gds.GeData.size();
                gds.Monitoring = me;
                iflog.Log__c += '\nNumberOfRecord=' + gds.GeData.size() + ' ';


                NFMUtil.Monitoring Monitoring = new NFMUtil.Monitoring();
                Monitoring.Tag = gds.Monitoring.Tag;
                Monitoring.Sender = gds.Monitoring.Sender;
                Monitoring.Receiver = gds.Monitoring.Receiver;
                Monitoring.MessageType = gds.Monitoring.MessageType;
                Monitoring.MessageGroupNumber = gds.Monitoring.MessageGroupNumber;
                Monitoring.NumberOfRecord = gds.Monitoring.NumberOfRecord;
                Monitoring.TransmissionDateTime = gds.Monitoring.TransmissionDateTime;
                Monitoring.Text = '';

                NFM601 nfm601 = new NFM601();
                NFM601.GeDatas = new GeDatas();
                NFM601.GeDatas = gds;

                rowData = NFMUtil.makeRowData(Monitoring, LOG_TYPE, nfm601);
                execute(rowData, iflog);
            }

        } catch (Exception ex) {
            // エラーが発生した場合
            logstr += ex.getMessage();
            iflog.ErrorLog__c += ex.getMessage() + '\n';
            iflog.ErrorLog__c += ex.getStackTraceString() + '\n';
        }
        if (rowData != null) {
            upsert rowData;
        }
        iflog.Log__c = logstr;
        upsert iflog;

    }

    /**
     * 接口发送失败 根据BatchLogId进行手动发送
     * @Author   XHL
     * @DateTime 2021-07-22
     * @param    rowDataId  [BatchLogId]
     */
    public static void ManualExecute(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) NFM601Controller.execute(row[0], null);
    }
    /**
     * 逻辑正常执行发送
     * @Author   XHL
     * @DateTime 2021-07-22
     * @param    rowDataSFDC [BatchLogId]
     * @param    iflog       [执行情况记录]
     */
    public static void execute(BatchIF_Log__c rowDataSFDC, BatchIF_Log__c iflog) {
        Integer batch_retry_max_cnt = Integer.valueOf(System.Label.batch_retry_max_cnt);
        
        logstr += rowDataSFDC.MessageGroupNumber__c + ' start\n';
        Boolean needUpdateIflog = false;
        if (iflog == null) {
            needUpdateIflog = true;
            iflog = new BatchIF_Log__c();
            iflog.Type__c = LOG_TYPE;
            iflog.MessageGroupNumber__c = rowDataSFDC.MessageGroupNumber__c;
            iflog.Log__c = logstr;
            iflog.ErrorLog__c = '';

        } else {
            needUpdateIflog = true;
            iflog.Type__c = LOG_TYPE;
            iflog.MessageGroupNumber__c = rowDataSFDC.MessageGroupNumber__c;
            logstr = iflog.Log__c;
        }

        try {
            String data = NFMUtil.getRowDataStr(rowDataSFDC);
            System.debug('data--------0>'+data);

            String jsonReplace =  JsonReplace(data);
            if (String.isNotBlank(jsonReplace)) {
                data = jsonReplace;
            }
            System.debug('data--------1>'+data);
            status = NFMUtil.sendToSapRet(data, NFMUtil.NFM601_ENDPOINT);
            //status = Label.X601test;   
            //Integer num = Integer.valueOf(Label.X601test);
            if ('Accepted'.equals(status)) {
                logstr += status + '\n';
                rowDataSFDC.retry_cnt__c = 0;
                needUpdateIflog = true;
                logstr += 'end';
            } else {
                // 异常重发
                logstr += 'status=' + status;
                rowDataSFDC = NFMUtil.LogAutoSend(rowDataSFDC, null, status);
            }
            System.debug('NFM601Log--status->' + status);
        } catch (Exception ex) {
            // TODO IOException

            // 异常重发
            // Callout from triggers are currently not supported.
            if (!String.valueOf(ex.getMessage()).contains('Callout from triggers')) {
                logstr += ex.getMessage();
                iflog.ErrorLog__c += ex.getMessage() + '\n';
                iflog.ErrorLog__c += ex.getStackTraceString() + '\n';
                needUpdateIflog = true;
            }
            rowDataSFDC = NFMUtil.LogAutoSend(rowDataSFDC, ex, null);
        }
        iflog.Log__c = logstr;
        if (needUpdateIflog) {
            upsert iflog;
            upsert rowDataSFDC;
        }


    }

    //查找 三证资质最早有效期(经销商)
    public static Map < Id, String > getLicenceEarliestDate(Set < Id > agencySet) {
        Map < Id, String > result = new Map < Id, String > ();

        List < License_Information__c > getLicenceList = [
            SELECT Id, ValidFrom__c, LicenseAndAccount__c
            FROM License_Information__c
            WHERE LicenseAndAccount__c In: agencySet AND ValidFrom__c != null
            ORDER BY LicenseAndAccount__c, ValidFrom__c desc
        ];
        if (getLicenceList.size() > 0) {
            for (License_Information__c li: getLicenceList) {
                Id accountId = li.LicenseAndAccount__c;
                String validFromStr = NFMUtil.formatDate2Str(li.ValidFrom__c);
                result.put(accountId, validFromStr);
            }
        }

        return result;
    }
    //查找 最晚合同有效期（契约）
    public static Map < Id, String > getAgencyContractLatestDate(Set < Id > agencySet) {
        Map < Id, String > result = new Map < Id, String > ();

        List < Account > getAgencyContractList = [
            SELECT Id, Name, Contract_End_Date__c, Agent_Ref__c
            FROM Account
            WHERE Agent_Ref__c IN: agencySet AND Contract_End_Date__c != null AND RecordTypeId = '01210000000QjCNAA0'
            ORDER BY Agent_Ref__c, Contract_End_Date__c
        ];
        if (getAgencyContractList.size() > 0) {
            for (Account acc: getAgencyContractList) {
                Id accountId = acc.Agent_Ref__c;
                String contractEndDateStr = NFMUtil.formatDate2Str(acc.Contract_End_Date__c);
                result.put(accountId, contractEndDateStr);
            }
        }
        return result;
    }
    /**
     * [因LMS系统timestamp有6分钟时效性，为了可以在系统宕机后，批量发送，用当前时间替换BatchLog日志里的timestamp的值]
     * @param  data [json字符串]
     * @return      [json字符串]
     */
    public static String JsonReplace(String data){
        
        List<String> jsonList = data.split(',');
        System.debug('jsonList---->'+jsonList);
        String jsonStr00 = '';
        Integer num = 1;
        String timestamp = String.valueOf(DateTime.now().getTime());
        for(String str:data.split(',')){
            if (str.contains('timestamp')) {
                system.debug('str--->'+str);
                str = '\"timestamp\"'+':'+'\"'+ timestamp +'\"';      
            }
            jsonStr00 += str;
            if (num++ != data.length()) {
               jsonStr00 += ','; 
            }
            
        }
        String result = jsonStr00.substring(0,jsonStr00.length()-1);
        System.debug('jsonStr00--->'+jsonStr00.substring(0,jsonStr00.length()-1));
        return result;
    }
}