using Etcdserverpb;
using Google.Protobuf.WellKnownTypes;
using HealthMonitor.Common;
using HealthMonitor.Common.helper;
using HealthMonitor.Model.Service.Mapper;
using HealthMonitor.Service.Biz;
using HealthMonitor.Service.Biz.db;
using HealthMonitor.Service.Cache;
using HealthMonitor.Service.Etcd;
using HealthMonitor.Service.MessageQueue;
using HealthMonitor.Service.Resolver.Interface;
using HealthMonitor.Service.Sub;
using HealthMonitor.Service.Sub.Topic.Model;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using TelpoDataService.Util.Clients;
using TelpoDataService.Util.Entities.GpsCard;
using TelpoDataService.Util.Entities.GpsLocationHistory;
using TelpoDataService.Util.Models;
using TelpoDataService.Util.QueryObjects;

namespace HealthMonitor.Service.Resolver
{
    public class PregnancyHeartRateResolver : IResolver
    {
        private readonly ILogger<PregnancyHeartRateResolver> _logger;
        private readonly TDengineService _serviceTDengine;

        private readonly DeviceCacheManager _deviceCacheMgr;
        private readonly IotApiService _serviceIotApi;


        private readonly AsyncLocal<string> _messageId = new();
        private readonly AsyncLocal<HisGpsHeartRate> _msgData = new();
        private readonly HttpHelper _httpHelper = default!;
        private readonly EtcdService _serviceEtcd;

        private readonly GpsLocationHistoryAccessorClient<HisGpsFetalHeartRate> _hisFetalHeartApiClient;
        private readonly GpsLocationHistoryAccessorClient<HisGpsFetalMovement> _hisFetalMovementApiClient;

        private readonly FetalMovementNormalValueRangeCacheManager _mgrFetalMovementNormalValueRangeCache;

        private readonly MqProcessLogic _serviceMqProcess;

        private static int[] SCHEDULE_HOUR = new int[] {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22};

        private static int[] ODD_SCHEDULE_HOUR = new int[] { 1, 3, 5, 7, 9, 11,13, 15, 17, 19, 21, 23 };
        // 延时胎心计算间隔周期
        private static int INTERVAL_FHR=15; 




        public PregnancyHeartRateResolver(ILogger<PregnancyHeartRateResolver> logger,
            HttpHelper httpHelper, EtcdService serviceEtcd, DeviceCacheManager deviceCacheMgr,
            MqProcessLogic serviceMqProcess,
            IotApiService iotApiService, TDengineService serviceDengine, FetalMovementNormalValueRangeCacheManager fetalMovementNormalValueRangeCacheMgr,
            GpsLocationHistoryAccessorClient<HisGpsFetalHeartRate> hisFetalHeartApiClient,
            GpsLocationHistoryAccessorClient<HisGpsFetalMovement> hisFetalMovementApiClient
            )
        {
            _logger = logger;
            _httpHelper = httpHelper;
            _serviceEtcd = serviceEtcd;
            _serviceTDengine = serviceDengine;
            _deviceCacheMgr = deviceCacheMgr;
            _serviceIotApi = iotApiService;
            _serviceMqProcess = serviceMqProcess;
            _hisFetalHeartApiClient = hisFetalHeartApiClient;
            _hisFetalMovementApiClient = hisFetalMovementApiClient;
            _mgrFetalMovementNormalValueRangeCache = fetalMovementNormalValueRangeCacheMgr;
        }

        public void SetResolveInfo(PackageMsgModel msg)
        {
            var topicHmPregnancyHeartRate = JsonConvert.DeserializeObject<TopicHmPregnancyHeartRate>(msg.DetailData.ToString()!);
            _messageId.Value = msg.MessageId;
            _msgData.Value = new HisGpsHeartRate()
            {
                HeartRateId = topicHmPregnancyHeartRate!.PregnancyHeartRateId,
                MessageId = topicHmPregnancyHeartRate!.MessageId,
                Serialno = topicHmPregnancyHeartRate!.Serialno,
                HeartRate = topicHmPregnancyHeartRate.PregnancyHeartRate,
                LastUpdate = DateTimeUtil.GetDateTimeFromUnixTimeMilliseconds(SafeType.SafeInt64(topicHmPregnancyHeartRate.LastUpdate) / 1000000),
                CreateTime = DateTimeUtil.GetDateTimeFromUnixTimeMilliseconds(SafeType.SafeInt64(topicHmPregnancyHeartRate.CreateTime) / 1000000),
                Method = topicHmPregnancyHeartRate!.Method,
                IsDisplay = topicHmPregnancyHeartRate!.IsDisplay ? 1 : 0
            };
        }
        public override string ToString()
        {
            return $"{nameof(PregnancyHeartRateResolver)}[{_messageId.Value}]";
        }

        public async Task ExecuteMessageAsync()
        {
            var messageId = _messageId.Value;
            var heartRate = _msgData.Value!;

            try
            {

                var watchConfig = await _deviceCacheMgr.GetGpsDeviceWatchConfigCacheObjectBySerialNoAsync(heartRate.Serialno, "0067");
                var isFetalHeartEnable = watchConfig != null && (int)watchConfig["enabled"]! == 1;

                if (isFetalHeartEnable)
                {
                    //_logger.LogInformation($"{heartRate.Serialno} 计算胎心胎动启动");
                    #region 定时下发触发器(定时建模)
                    var key = $"health_monitor/schedule_push/pregnancy_heart_rate/imei/{heartRate.Serialno}";
                    var schedule_push = await _serviceEtcd.GetValAsync(key).ConfigureAwait(false);

                    if (string.IsNullOrWhiteSpace(schedule_push))
                    {
                        // 注册首次下推
                        var interval = 0;
                        // 获取当前时间
                        DateTime now = DateTime.Now;
                        var rand = new Random();
                        var pushSec = rand.Next(59);
                        int pushMin = int.TryParse(heartRate.Serialno.AsSpan(heartRate.Serialno.Length - 1), out pushMin) ? pushMin : 10;
                        // 计算距离下一个$interval天后的8点的时间间隔
                        DateTime nextRunTime = new DateTime(now.Year, now.Month, now.Day, 6, pushMin, pushSec).AddDays(interval);
                        TimeSpan timeUntilNextRun = nextRunTime - now;

                        if (timeUntilNextRun < TimeSpan.Zero)
                        {
                            timeUntilNextRun = timeUntilNextRun.Add(TimeSpan.FromDays(1));
                            nextRunTime += TimeSpan.FromDays(1);
                        }

                        var ttl = (long)timeUntilNextRun.TotalSeconds;
                        var data = new
                        {
                            imei = heartRate.Serialno,
                            create_time = now.ToString("yyyy-MM-dd HH:mm:ss"),
                            ttl,
                            next_run_time = nextRunTime.ToString("yyyy-MM-dd HH:mm:ss")
                        };
                        var result = JsonConvert.SerializeObject(data);
                        await _serviceEtcd.PutValAsync(key, result, ttl, false).ConfigureAwait(false);

                    }

                    #endregion
                    //_logger.LogInformation($"{heartRate.Serialno} 触发定时建模");

                    // 高频心率采样间隔 highFreqSampleInterval = highFreqSampleInterval 最小highFreqSampleInterval=60)
                    var highFreqSampleInterval = (int)watchConfig!["highFreqSampleInterval"]! >= 60 ? (int)watchConfig!["highFreqSampleInterval"]!:60;
                    // 触发高频监测的心率上限值
                    var triggerHighFreqHigh = (int)watchConfig["triggerHighFreqHigh"]!;
                    // 触发高频监测的心率下限值
                    var triggerHighFreqLow = (int)watchConfig["triggerHighFreqLow"]!;
                    // 暂时处理
                    triggerHighFreqLow = triggerHighFreqLow > 60 && triggerHighFreqLow < 67 ? 60 : triggerHighFreqLow;
                    //停止高频心率采样心率连续正常次数
                    var stopHighFreqSampleCount = (int)watchConfig["stopHighFreqSampleCount"]!;
                    // 高频心率采集时长 0 为持续采集,非零为高频心率的采集时长
                    //var highFreqSampleTimes = (int)watchConfig["highFreqSampleTimes"]!;
                    var highFreqSampleTimes = 540;
                    // 告警上限阀值
                    var upperAlarmThreshold = (int)watchConfig["upperAlarmThreshold"]!;
                    // 告警下限阀值
                    var lowerAlarmThreshold = (int)watchConfig["lowerAlarmThreshold"]!;
                    // EDOC
                    var edoc = DateTimeUtil.ToDateTime(watchConfig!["EDOC"]!.ToString());
                    // interval (分钟) 固定15分钟
                    var intervalFHR = 15;//int)watchConfig["interval"]!;

                    var daysPhr = await _serviceTDengine.GetBySerialNoAsync<PregnancyHeartRateModel>(heartRate.Serialno, 7);
                    var phr = daysPhr
                        .Where(p => p.LastUpdate <= heartRate.LastUpdate)
                        .ToList();
                    var nonFreqPhr = GetNonFreqPregnancyHeartRate(phr, highFreqSampleInterval);
                    if (nonFreqPhr.Count >= 30)
                    {
                        #region 定时计算胎动数据触发器两小时间隔开始(奇数小时计算)
                        /**
                        var fetalMovementKey = $"health_monitor/schedule_push/cal_fetal_movement/imei/{heartRate.Serialno}";
                        var rand = new Random();
                        var pushSec = rand.Next(59);
                        int pushMin = int.TryParse(heartRate.Serialno.AsSpan(heartRate.Serialno.Length - 1), out pushMin) ? pushMin : 10;

                        DateTime fmScheduleNow = DateTime.Now;
                        int hour = fmScheduleNow.Hour;
                        int selectedScheduleHour;

                        // 使用模运算来获取相应的ODD_SCHEDULE_HOUR
                        if (hour % 2 == 0)
                        {
                            selectedScheduleHour = ODD_SCHEDULE_HOUR[hour / 2 % ODD_SCHEDULE_HOUR.Length];
                        }
                        else
                        {
                            selectedScheduleHour = ODD_SCHEDULE_HOUR[(hour + 1) / 2 % ODD_SCHEDULE_HOUR.Length];
                        }

                        
                        DateTime scheduledDateTime = new DateTime(
                             fmScheduleNow.Year,
                             fmScheduleNow.Month,
                             fmScheduleNow.Day,
                             selectedScheduleHour,
                             pushMin, 
                             pushSec  
                         );

                        // 如果生成的时间在当前时间之前
                        // 或者 fmScheduleNow 在 23 点之后并且 selectedScheduleHour 在 1 点(即次日)
                        if (scheduledDateTime < fmScheduleNow || (fmScheduleNow.Hour >= 23 && selectedScheduleHour <= 1))
                        {
                            scheduledDateTime = scheduledDateTime.AddDays(1);
                        }

                        TimeSpan timeUntilNextRun = scheduledDateTime - fmScheduleNow;
                        var ttl = (long)timeUntilNextRun.TotalSeconds;

                        await SetIntervalTriggerAsync(fetalMovementKey, heartRate.Serialno, ttl, heartRate);
                        _logger.LogInformation($"{heartRate.Serialno}-{heartRate.MessageId} 创建计划统计胎动时间{scheduledDateTime.ToString("yyyy-MM-dd HH:mm:ss")}");
                        */
                        #endregion


                        #region 定时计算胎动数据触发器每小时间隔开始,延时一个小时计算
                        ///当前时间是的0~1小时返回2小时 ,
                        ///当前时间是的1~2小时返回3小时 ,如此类推,
                        ///当前时间是的21~22小时返回23小时 
                        ///当前时间是的23~0小时返回次日1小时

                        var fetalMovementKey = $"health_monitor/schedule_push/cal_fetal_movement/imei/{heartRate.Serialno}";
                        var rand = new Random();
                        var pushSec = rand.Next(59);
                        int pushMin = int.TryParse(heartRate.Serialno.AsSpan(heartRate.Serialno.Length - 1), out pushMin) ? pushMin : 10;

                        DateTime fmScheduleNow = DateTime.Now;
                        int hour = fmScheduleNow.Hour;
                        int selectedScheduleHour=DateTimeUtil.GetNextHour(fmScheduleNow.Hour);



                        DateTime scheduledDateTime = new DateTime(
                             fmScheduleNow.Year,
                             fmScheduleNow.Month,
                             fmScheduleNow.Day,
                             selectedScheduleHour,
                             pushMin,
                             pushSec
                         );

                        // 跨天
                        if (selectedScheduleHour == 1)
                        {
                            scheduledDateTime = scheduledDateTime.AddDays(1);
                        }

                        TimeSpan timeUntilNextRun = scheduledDateTime - fmScheduleNow;
                        var ttl = (long)timeUntilNextRun.TotalSeconds;

                        await SetIntervalTriggerAsync(fetalMovementKey, heartRate.Serialno, ttl, heartRate);
                        _logger.LogInformation($"{heartRate.Serialno}-{heartRate.MessageId} 创建计划统计胎动时间{scheduledDateTime.ToString("yyyy-MM-dd HH:mm:ss")}");

                        #endregion


                        #region 计算胎心数据(按心率时间LastUpdate)
                        var commonPHR = await _serviceTDengine.GetLastAsync<PregnancyCommonHeartRateModel>(heartRate.Serialno);
                        // 如果commonPHR为空或已建模已过期,进行建模和保存
                        if (commonPHR == null || !commonPHR.CreateTime.Date.Equals(DateTime.Now.Date))
                        // 获取当天 6:11 的时间点, 6:11 所有数据都已经全部建模
                        //if (commonPHR == null || commonPHR.CreateTime < DateTime.Today.AddHours(6).AddMinutes(11))
                        {
                            // 处理孕妇业务,计算一般心率并下发
                            commonPHR = await _serviceTDengine.InitPregnancyCommonHeartRateModeAsync(heartRate.Serialno, highFreqSampleInterval: highFreqSampleInterval);
                            // 建模完成
                            var flag = await _serviceIotApi.SetFetalConfig(heartRate.Serialno, 1, commonPHR!.MaxValue, commonPHR!.MinValue);
                            _logger.LogInformation($"{heartRate.Serialno} 记录数量足够,建模完成");
                            // 保存到TDengine数据库
                            await _serviceTDengine.InsertAsync<PregnancyCommonHeartRateModel>("hm_pchr", commonPHR!);
                            _logger.LogInformation($"保存TDengine完成");
                        }

                        // 获取最近的两个记录,并计算它们的 LastUpdate 时间差
                        var firstTwoPhr = phr.OrderByDescending(i => i.LastUpdate).Take(2).Select(i => i.LastUpdate).ToList();
                        var timeDiff = firstTwoPhr[0] - firstTwoPhr[1];

                        // 如果需要,将时间差转换为秒
                        var timeDiffInSeconds = timeDiff.TotalSeconds;

                        // 高频统计结束时间
                        var FreqStatsEnd = DateTime.Now;


                        // 高频心率启动(在高频第二条才能判断)
                        if (timeDiffInSeconds <= highFreqSampleInterval)
                        {
                            // 设置延时计算高频心率的胎心
                            var freqHearRateHey = $"health_monitor/schedule_push/cal_freqhr_fetal_heart_rate/imei/{heartRate.Serialno}";
                            var phrFreqstatus = await _deviceCacheMgr.GetPregnancyHeartRateFreqStatusAsync(heartRate.Serialno);
                            if (phrFreqstatus == null)
                            {
                                /// 设置高频状态
                                _logger.LogInformation($"{heartRate.Serialno} 进入高频心率启动状态 timeDiffInSeconds {timeDiffInSeconds},highFreqSampleInterval:{highFreqSampleInterval}");
                                // 设置高频状态
                                _logger.LogInformation($"{heartRate.Serialno} phr.Count {phr.Count}");
                                var freqFirstPhr = phr.OrderByDescending(i => i.LastUpdate)
                                    .Skip(1) //在高频第二条才能判断,所以要去除本条记录
                                    .First();
                                await _deviceCacheMgr.SetPregnancyHeartRateFreqStatusAsync(heartRate.Serialno, freqFirstPhr);
                                _logger.LogInformation($"{heartRate.Serialno} 设置高频状态");
                                phrFreqstatus = await _deviceCacheMgr.GetPregnancyHeartRateFreqStatusAsync(heartRate.Serialno);
                                HisGpsHeartRate freqFirstHR = new()
                                {
                                    CreateTime = freqFirstPhr.CreateTime,
                                    DeviceKey = freqFirstPhr.DeviceKey,
                                    HeartRate = freqFirstPhr.PregnancyHeartRate,
                                    HeartRateId = freqFirstPhr.PregnancyHeartRateId,
                                    IsDisplay = freqFirstPhr.IsDisplay ? 1 : 0,
                                    LastUpdate = freqFirstPhr.LastUpdate,
                                    MessageId = freqFirstPhr.MessageId,
                                    Method = freqFirstPhr.Method,
                                    PersonId = freqFirstPhr.PersonId,
                                    Serialno = freqFirstPhr.SerialNumber,
                                };
                                await SetFreqHeartRateTriggerAsync(freqHearRateHey, heartRate.Serialno, highFreqSampleInterval, freqFirstHR);
                            }
                            // 续租延时计算高频心率的胎心
                            await SetFreqHeartRateTriggerAsync(freqHearRateHey, heartRate.Serialno, highFreqSampleInterval);

                            /// phr  PregnancyHeartRate 连续连续正常次数个值都是正常(大于等于triggerHighFreqLow,少于等于triggerHighFreqHig),
                            /// 取连续正常次数正常值的平均值,推送到api/v1/open/OpenIot/SetFetalHeartRateConfig
                            #region 检查高频状态是否连续12个心率值都是正常的
                            // 获取最近连续正常次数个心率记录
                            //_logger.LogInformation($"{heartRate.Serialno} 设置 stopHighFreqSampleCount {stopHighFreqSampleCount}");

                            //var lastPhr = phr.OrderByDescending(i => i.LastUpdate).Take(stopHighFreqSampleCount).ToList();
                            var lastPhr = phr.Where(i => i.LastUpdate >= phrFreqstatus!.LastUpdate)
                                .OrderByDescending(i => i.LastUpdate).Take(stopHighFreqSampleCount).ToList();
                            _logger.LogInformation($"{heartRate.Serialno} lastPhr.Count {lastPhr.Count},stopHighFreqSampleCount {stopHighFreqSampleCount}");
                            _logger.LogInformation($"{heartRate.Serialno} count :{lastPhr.Count >= stopHighFreqSampleCount}");
                            _logger.LogInformation($"{heartRate.Serialno} All {lastPhr.All(i => i.PregnancyHeartRate >= triggerHighFreqLow && i.PregnancyHeartRate <= triggerHighFreqHigh)}");

                            // 检查是否连续12个值都是正常的
                            if ((lastPhr.Count >= stopHighFreqSampleCount) &&
                                lastPhr.All(i => i.PregnancyHeartRate >= triggerHighFreqLow && i.PregnancyHeartRate <= triggerHighFreqHigh)
                                )
                            {
                                var avgPhr = lastPhr.Select(i => i.PregnancyHeartRate).Average();
                                // 计算一般心率得到胎心系数
                                //await SaveAndPushFreqFetalHeartRateAsync(heartRate, upperAlarmThreshold, lowerAlarmThreshold, avgPhr, DateTimeUtil.ConvertToTimeStamp(DateTime.Now).ToString());
                                // 高频数据不建模
                                FreqStatsEnd = (DateTime)heartRate.LastUpdate!;
                                _logger.LogInformation($"{heartRate.Serialno} 高频状态已经持续{(FreqStatsEnd - phrFreqstatus!.LastUpdate).TotalSeconds} 秒,连续 {stopHighFreqSampleCount} 次采样心率正常,将下发指令");

                                var freqSaveAndPushFetalHeartRate = await _deviceCacheMgr.GetBizIntervalAsync(heartRate.Serialno, "SaveAndPushFetalHeartRate");
                                // 高频不停,15分钟内只下发一条
                                if (string.IsNullOrEmpty(freqSaveAndPushFetalHeartRate))
                                {
                                    //await SaveAndPushFetalHeartRateAsync(heartRate, commonPHR, upperAlarmThreshold, lowerAlarmThreshold, avgPhr, DateTimeUtil.ConvertToTimeStamp(phrFreqstatus!.LastUpdate).ToString(), phrFreqstatus!.LastUpdate, FreqStatsEnd);

                                    heartRate.HeartRate = (int)avgPhr;
                                    //await SaveAndPushFetalHeartRateEndFreqHeartRateAsync(heartRate, commonPHR, upperAlarmThreshold, lowerAlarmThreshold, DateTimeUtil.ConvertToTimeStamp(phrFreqstatus!.LastUpdate).ToString(), phrFreqstatus!.LastUpdate, FreqStatsEnd);

                                    var ts = DateTimeUtil.GetTimeDifferenceInSeconds((DateTime)heartRate.LastUpdate!, phrFreqstatus!.LastUpdate);  
                                    // 判断是否够highFreqSampleTimes,540s
                                    if (ts < highFreqSampleTimes)
                                    {
                                        /// 不够10分钟最近12个数据的最小值生成胎心值
                                        heartRate.HeartRate = lastPhr.Select(i=>i.PregnancyHeartRate).Min();
                                    }
                                    await SaveAndPushFetalHeartRateEndFreqHeartRateAsync(heartRate, commonPHR,highFreqSampleTimes ,upperAlarmThreshold, lowerAlarmThreshold, DateTimeUtil.ConvertToTimeStamp(phrFreqstatus!.LastUpdate).ToString(), phrFreqstatus!.LastUpdate, FreqStatsEnd);
                                   
                                    // 删除高频状态的首条记录
                                    await _deviceCacheMgr.DelPregnancyHeartRateFreqStatusAsync(heartRate.Serialno);
                                    // 设置15分的SaveAndPushFetalHeartRate业务间隔
                                    await _deviceCacheMgr.SetBizIntervalAsync(heartRate.Serialno, "SaveAndPushFetalHeartRate");
                                    _logger.LogInformation($"{heartRate.Serialno} 连续 {stopHighFreqSampleCount} 次采样心率正常,结束高频心率状态, timeDiffInSeconds {timeDiffInSeconds},highFreqSampleInterval:{highFreqSampleInterval},高频状态持续{((DateTime)heartRate.LastUpdate - phrFreqstatus!.LastUpdate).TotalSeconds} 秒,高频心率平均值:{(int)avgPhr}");
                                }
                                else
                                {
                                    _logger.LogWarning($"{heartRate.Serialno} 连续 {stopHighFreqSampleCount} 次采样心率正常,设备端应该结束高频状态,但设备端没有结束高频,平台高频15分钟内已经下发过指令");
                                }

                            }
                            else
                            {
                                _logger.LogInformation($"{heartRate.Serialno} 处于高频状态...");
                            }
                            #endregion
                        }
                        // 高频心率结束或常规心率
                        else
                        {
                            var phrFreqstatus = await _deviceCacheMgr.GetPregnancyHeartRateFreqStatusAsync(heartRate.Serialno);
                            // 高频心率结束
                            if (phrFreqstatus != null)
                            {
                                /// 在highFreqSampleTimes=0一直异常(大于等于triggerHighFreqLow,少于等于triggerHighFreqHig),
                                /// 取所有值的平均值,推送胎心数据到api/v1/open/OpenIot/SetFetalHeartRateConfig
                                if (highFreqSampleTimes == 0)
                                {
                                    var lastPhr = phr.OrderByDescending(i => i.LastUpdate)
                                           .Where(i => i.LastUpdate >= phrFreqstatus?.LastUpdate)
                                           .Skip(1) // 去除首条
                                           .Where(i => i.PregnancyHeartRate < triggerHighFreqLow || i.PregnancyHeartRate > triggerHighFreqHigh);
                                           //.Select(i => i.PregnancyHeartRate);
                                           //.Average();

                                    var avgPhr  = lastPhr.Select(i => i.PregnancyHeartRate).Average();
                                    // 推送胎心数据到 api/v1/open/OpenIot/SetFetalHeartRateConfig
                                    // 计算一般心率得到胎心系数
                                    // 高频数据不建模
                                    FreqStatsEnd = firstTwoPhr[1];
                                    _logger.LogInformation($"{heartRate.Serialno} 高频状态已经持续{(FreqStatsEnd - phrFreqstatus!.LastUpdate).TotalSeconds} 秒,highFreqSampleTimes={highFreqSampleTimes}秒,即将结束高频状态,高频心率平均值:{(int)avgPhr},将下发指令");

                                    //await SaveAndPushFreqFetalHeartRateAsync(heartRate, commonPHR, upperAlarmThreshold, lowerAlarmThreshold, avgPhr, DateTimeUtil.ConvertToTimeStamp(phrFreqstatus!.LastUpdate).ToString());
                                    //await SaveAndPushFetalHeartRateAsync(heartRate, commonPHR, upperAlarmThreshold, lowerAlarmThreshold, avgPhr, DateTimeUtil.ConvertToTimeStamp(phrFreqstatus!.LastUpdate).ToString(), phrFreqstatus!.LastUpdate, FreqStatsEnd);

                                    heartRate.HeartRate = (int)avgPhr;
                                    //await SaveAndPushFetalHeartRateEndFreqHeartRateAsync(heartRate, commonPHR, upperAlarmThreshold, lowerAlarmThreshold, DateTimeUtil.ConvertToTimeStamp(phrFreqstatus!.LastUpdate).ToString(), phrFreqstatus!.LastUpdate, FreqStatsEnd);
                                    var ts = DateTimeUtil.GetTimeDifferenceInSeconds((DateTime)heartRate.LastUpdate!, phrFreqstatus!.LastUpdate);
                                    // 判断是否够highFreqSampleTimes,540s
                                    if (ts < highFreqSampleTimes)
                                    {
                                        /// 不够10分钟最近12个数据的最小值生成胎心值
                                        heartRate.HeartRate = lastPhr.Select(i => i.PregnancyHeartRate).Min();
                                    }
                                    await SaveAndPushFetalHeartRateEndFreqHeartRateAsync(heartRate, commonPHR, highFreqSampleTimes, upperAlarmThreshold, lowerAlarmThreshold, DateTimeUtil.ConvertToTimeStamp(phrFreqstatus!.LastUpdate).ToString(), phrFreqstatus!.LastUpdate, FreqStatsEnd);

                                }

                                /// 在highFreqSampleTimes>0一直异常(大于等于triggerHighFreqLow,少于等于triggerHighFreqHig),
                                /// 取所有值的平均值,推送胎心数据到api/v1/open/OpenIot/SetFetalHeartRateConfig
                                if (highFreqSampleTimes > 0 && heartRate.LastUpdate >= (phrFreqstatus?.LastUpdate.AddSeconds(highFreqSampleTimes)))
                                {

                                    // 获取高频心率数据个数
                                    var filterPhr = phr
                                          .Where(i => i.LastUpdate >= phrFreqstatus?.LastUpdate)
                                          .Skip(1)
                                          .ToList();

                                    _logger.LogInformation($"{heartRate.Serialno} 高频周期 {phrFreqstatus?.LastUpdate.ToString("yyyy-MM-dd HH:mm:ss")}--{firstTwoPhr[1].ToString("yyyy-MM-dd HH:mm:ss")} 产生高频心率数量 {filterPhr.Count} 条");

                                    // 高频心率数据大于stopHighFreqSampleCount/12个才计算胎心数据
                                    //
                                    if (filterPhr.Count > stopHighFreqSampleCount)
                                    {
                                        FreqStatsEnd = firstTwoPhr[1];

                                        var avgPhr = filterPhr
                                            .OrderByDescending(i => i.LastUpdate)
                                            .Take(stopHighFreqSampleCount) // 计算最后12条
                                            .Select(i => i.PregnancyHeartRate).Average();

                                        _logger.LogInformation($"{heartRate.Serialno} 高频状态已经持续{(FreqStatsEnd - phrFreqstatus!.LastUpdate).TotalSeconds} 秒,超过约定的 {highFreqSampleTimes} 秒,即将结束高频状态,高频心率平均值:{(int)avgPhr},将下发指令");
                                        //计算高频
                                        //await SaveAndPushFetalHeartRateAsync(heartRate, commonPHR, upperAlarmThreshold, lowerAlarmThreshold, avgPhr, DateTimeUtil.ConvertToTimeStamp(phrFreqstatus!.LastUpdate).ToString(), phrFreqstatus!.LastUpdate, FreqStatsEnd);
                                        heartRate.HeartRate = (int)avgPhr;
                                        //await SaveAndPushFetalHeartRateEndFreqHeartRateAsync(heartRate, commonPHR, upperAlarmThreshold, lowerAlarmThreshold, DateTimeUtil.ConvertToTimeStamp(phrFreqstatus!.LastUpdate).ToString(), phrFreqstatus!.LastUpdate, FreqStatsEnd);

                                        // 判断是否够highFreqSampleTimes,540s
                                        var lastPhr = filterPhr
                                            .OrderByDescending(i => i.LastUpdate)
                                            .Take(stopHighFreqSampleCount);
                                        var ts = DateTimeUtil.GetTimeDifferenceInSeconds((DateTime)heartRate.LastUpdate!, phrFreqstatus!.LastUpdate);
                                        
                                        if (ts < highFreqSampleTimes)
                                        {
                                            /// 不够10分钟最近12个数据的最小值生成胎心值
                                            heartRate.HeartRate = lastPhr.Select(i => i.PregnancyHeartRate).Min();
                                        }
                                        await SaveAndPushFetalHeartRateEndFreqHeartRateAsync(heartRate, commonPHR, highFreqSampleTimes, upperAlarmThreshold, lowerAlarmThreshold, DateTimeUtil.ConvertToTimeStamp(phrFreqstatus!.LastUpdate).ToString(), phrFreqstatus!.LastUpdate, FreqStatsEnd);
                                    }
                                    else
                                    {
                                        _logger.LogWarning($"{heartRate.Serialno} 高频心率的数据不大于{stopHighFreqSampleCount}条,不进行高频数据的胎心计算");

                                    }

                                    // 删除高频状态的首条记录
                                    await _deviceCacheMgr.DelPregnancyHeartRateFreqStatusAsync(heartRate.Serialno);
                                    // (逐条计算)计算本次常规心率的胎心数据(高频结束后,实时处理)
                                   // await CalculateNormalFetalHeartRateAsync(heartRate, upperAlarmThreshold, lowerAlarmThreshold, intervalFHR, commonPHR);
                                    await CalculateNormalFetalHeartRateScheduleAsync(heartRate);

                                }
                                ///不满足持续10分钟highFreqSampleTimes或出现时间倒叙
                                ///
                                else
                                {

                                    // 高频结束后与常规的心率时间倒叙
                                    if ((firstTwoPhr[1] - phrFreqstatus!.LastUpdate).TotalSeconds < 0)
                                    {
                                        _logger.LogInformation($"{heartRate.Serialno} 高频结束出现时间倒叙,计算当条心率创建之前的高频心率");
                                        #region 计算当条心率创建之前的高频心率
                                        // 取得高频之后的所有数据
                                        var phrFlashBack = daysPhr.Where(p => p.LastUpdate >= phrFreqstatus!.LastUpdate)
                                            .OrderByDescending(i => i.LastUpdate);
                                        // 取得高频数据
                                        var freqCollection = phrFlashBack.ToList();
                                        //var freqCollection = new List<PregnancyHeartRateModel>();
                                        //PregnancyHeartRateModel? previousItem = null;

                                        //foreach (var item in phrFlashBack)
                                        //{
                                        //    if (previousItem != null)
                                        //    {
                                        //        var timeNextDiff = (previousItem!.LastUpdate - item.LastUpdate).TotalSeconds;
                                        //        if (timeNextDiff <= highFreqSampleInterval)
                                        //        {
                                        //            freqCollection.Add(item);
                                        //        }
                                        //    }
                                        //    previousItem = item;
                                        //}

                                        _logger.LogInformation($"{heartRate.Serialno} 高频数据个数{freqCollection.Count},触发高频开始时间{phrFreqstatus!.LastUpdate}");
                                        if (freqCollection.Count > stopHighFreqSampleCount)
                                        {
                                            // 计算高频产生的胎心
                                            var avgPhr = freqCollection
                                           .OrderByDescending(i => i.LastUpdate)
                                           .Take(stopHighFreqSampleCount) // 计算最后12条
                                           .Select(i => i.PregnancyHeartRate).Average();

                                            heartRate.HeartRate = (int)avgPhr;
                                            // await SaveAndPushFetalHeartRateEndFreqHeartRateAsync(heartRate, commonPHR, upperAlarmThreshold, lowerAlarmThreshold, DateTimeUtil.ConvertToTimeStamp(phrFreqstatus!.LastUpdate).ToString(), phrFreqstatus!.LastUpdate, FreqStatsEnd);
                                            //_logger.LogInformation($"{heartRate.Serialno} 高频数据个数{freqCollection.Count},触发高频开始时间{phrFreqstatus!.LastUpdate},高频心率平均值:{(int)avgPhr}");

                                            // 判断是否够highFreqSampleTimes,540s
                                            var lastPhr = freqCollection
                                           .OrderByDescending(i => i.LastUpdate)
                                           .Take(stopHighFreqSampleCount);
                                            var ts = DateTimeUtil.GetTimeDifferenceInSeconds((DateTime)heartRate.LastUpdate!, phrFreqstatus!.LastUpdate);
                                            if (ts < highFreqSampleTimes)
                                            {
                                                /// 不够10分钟最近12个数据的最小值生成胎心值
                                                heartRate.HeartRate = lastPhr.Select(i => i.PregnancyHeartRate).Min();
                                            }
                                            await SaveAndPushFetalHeartRateEndFreqHeartRateAsync(heartRate, commonPHR, highFreqSampleTimes, upperAlarmThreshold, lowerAlarmThreshold, DateTimeUtil.ConvertToTimeStamp(phrFreqstatus!.LastUpdate).ToString(), phrFreqstatus!.LastUpdate, FreqStatsEnd);

                                            _logger.LogInformation($"{heartRate.Serialno} 高频数据个数{freqCollection.Count},触发高频开始时间{phrFreqstatus!.LastUpdate},时间倒叙");
                                        }
                                        else
                                        {
                                            _logger.LogInformation($"{heartRate.Serialno} 时间倒叙触发计算高频心率的数据不足{stopHighFreqSampleCount}条,不进行胎心计算");

                                        }
                                        #endregion

                                    }
                                    else
                                    {
                                        _logger.LogInformation($"{heartRate.Serialno} 高频持续时间不足{highFreqSampleTimes},只持续{(firstTwoPhr[1] - phrFreqstatus!.LastUpdate).TotalSeconds} 秒");
                                    }
                                    // 删除高频状态的首条记录
                                    await _deviceCacheMgr.DelPregnancyHeartRateFreqStatusAsync(heartRate.Serialno);
                                    // (逐条计算)计算本次常规心率的胎心数据(高频结束后,实时处理)
                                    //await CalculateNormalFetalHeartRateAsync(heartRate, upperAlarmThreshold, lowerAlarmThreshold, intervalFHR, commonPHR);
                                    await CalculateNormalFetalHeartRateScheduleAsync(heartRate);
                                }

                                // 删除高频状态的首条记录
                                await _deviceCacheMgr.DelPregnancyHeartRateFreqStatusAsync(heartRate.Serialno);

                                _logger.LogInformation($"{heartRate.Serialno} 超时结束高频心率状态 timeDiffInSeconds {timeDiffInSeconds},highFreqSampleInterval:{highFreqSampleInterval},高频状态持续{(firstTwoPhr[1] - phrFreqstatus!.LastUpdate).TotalSeconds} 秒");

                               
                                //// 使用延后计算
                                //var fhrScheduleKey = $"health_monitor/schedule_push/cal_fetal_heart_rate/imei/{heartRate.Serialno}";
                                //var fhrScheduleTTL = 60;
                                //await SetIntervalTriggerAsync(fhrScheduleKey, heartRate.Serialno, fhrScheduleTTL, heartRate);
                            }
                            // 常规心率(本次心率可能是高频心率的首条,所以要使用延后计算胎心率)
                            else
                            {

                                // 本次心率可能是高频心率的首条,所以要使用本次常规心率延后计算胎心率
                                //var fhrScheduleKey = $"health_monitor/schedule_push/cal_fetal_heart_rate/imei/{heartRate.Serialno}";
                                //var fhrScheduleTTL = 30;
                                //await SetIntervalTriggerAsync(fhrScheduleKey, heartRate.Serialno, fhrScheduleTTL, heartRate);
                                //_logger.LogInformation($"{heartRate.Serialno} 延时50秒,判断当前数据是否为高频首条");

                                // 本次心率可能是高频心率的首条,所以要使用本次常规心率延后计算胎心率 查询30秒后是否有高频缓存
                                Thread thread = new(async () =>
                                {
                                    try
                                    {
                                        #region 休眠highFreqSampleInterval2秒
                                        var startTime = DateTime.Now;
                                        //var highFreqSampleInterval2 = (int)watchConfig!["highFreqSampleInterval"]!+5;
                                        var highFreqSampleInterval2 = highFreqSampleInterval;
                                        var during = TimeSpan.FromSeconds(highFreqSampleInterval2);
                                        while (true)
                                        {
                                            if (DateTime.Now - startTime > during)
                                            {
                                                break;
                                            }
                                            await Task.Delay(TimeSpan.FromSeconds(1));
                                        }
                                        #endregion
                                        var phrFreqstatus = await _deviceCacheMgr.GetPregnancyHeartRateFreqStatusAsync(heartRate.Serialno);
                                        _logger.LogInformation($"phrFreqstatus==null:{phrFreqstatus == null}");
                                        _logger.LogInformation($"phrFreqstatus.LastUpdate < heartRate.LastUpdate:{phrFreqstatus?.LastUpdate < heartRate.LastUpdate}");
                                        if (phrFreqstatus == null || phrFreqstatus.LastUpdate < heartRate.LastUpdate)
                                        {
                                            // (逐条计算)常规心率
                                            //await CalculateNormalFetalHeartRateAsync(heartRate, upperAlarmThreshold, lowerAlarmThreshold, intervalFHR, commonPHR);
                                            //_logger.LogInformation($"{heartRate.Serialno} 计算常规心率");

                                            // 延时计算常规心率
                                            await CalculateNormalFetalHeartRateScheduleAsync(heartRate);
                                        }

                                    }
                                    catch (Exception ex)
                                    {

                                        _logger.LogError($"处理延时计算异常:{ex.Message}, {ex.StackTrace}");
                                    }

                                });
                                thread.Start();
                            }
                        }

                        #endregion
                    }
                    else
                    {
                        _logger.LogInformation($"{heartRate.Serialno} 记录不足30条,建模中");
                    }
                }


            }
            catch (Exception ex)
            {

                _logger.LogError($"{heartRate.Serialno} 处理孕妇心率数据异常 \n{ex.Message}\n{ex.StackTrace}");
            }

        }
        /// <summary>
        /// (逐条计算)常规心率计算胎心数据
        /// </summary>
        /// <param name="heartRate"></param>
        /// <param name="upperAlarmThreshold"></param>
        /// <param name="lowerAlarmThreshold"></param>
        /// <param name="intervalFHR"></param>
        /// <param name="commonPHR"></param>
        /// <returns></returns>
        /**
        private async Task CalculateNormalFetalHeartRateAsync(HisGpsHeartRate heartRate, int upperAlarmThreshold, int lowerAlarmThreshold, int intervalFHR, PregnancyCommonHeartRateModel? commonPHR)
        {
            // 上15分钟的数据
            // 获取当前时间
            DateTime nowInterval = (DateTime)heartRate.LastUpdate!;
            if (nowInterval.Second > 0)
            {
                nowInterval = nowInterval.AddMinutes(1);
            }
            // 计算last_update到上一间隔的分钟数
            int minutesToSubtract = nowInterval.Minute % intervalFHR;

            // 计算上一间隔的时间
            DateTime previousInterval = nowInterval.AddMinutes(-minutesToSubtract).AddSeconds(-nowInterval.Second).AddMilliseconds(-nowInterval.Millisecond);

            // 使用 last_update 上一刻
            var sampleTimeFHR = DateTimeUtil.ConvertToTimeStamp(previousInterval).ToString();

            // 计算last_update到下一间隔的分钟数
            int minutesToAdd = intervalFHR - (nowInterval.Minute % intervalFHR);
            if (minutesToAdd == intervalFHR)
            {
                minutesToAdd = 0; // 如果已经是间隔,则不需要增加分钟
            }

            // 计算下一间隔的时间
            DateTime nextInterval = nowInterval.AddMinutes(minutesToAdd)
                                            .AddSeconds(-nowInterval.Second)
                                            .AddMilliseconds(-nowInterval.Millisecond);


            var daysPhr = await _serviceTDengine.GetBySerialNoAsync<PregnancyHeartRateModel>(heartRate.Serialno, 7);

            var normalPhrStatStartTime = nextInterval.AddMinutes(-intervalFHR);

            var normalPhrStatEndTime = nextInterval;

            _logger.LogInformation($"{heartRate.Serialno} 计算胎心数据, 周期:{normalPhrStatStartTime}-{normalPhrStatEndTime} ");
            var filteredPhr = daysPhr
                // 使用 last_update 下一刻
                .Where(i => i.LastUpdate <= normalPhrStatEndTime && i.LastUpdate >= normalPhrStatStartTime)
                .ToList();
            if (filteredPhr.Count == 0)
            {
                _logger.LogWarning($"{heartRate.Serialno}  周期:{normalPhrStatStartTime}-{normalPhrStatEndTime} 孕妇心率数据不足,{filteredPhr.Count}条记录");
                return;
            }
            var phrValue = filteredPhr.Count == 1
                ? filteredPhr.First().PregnancyHeartRate
                : filteredPhr.Average(i => i.PregnancyHeartRate);

            //await SaveAndPushFreqFetalHeartRateAsync(heartRate, commonPHR!, upperAlarmThreshold, lowerAlarmThreshold, phrValue, sampleTimeFHR);
            //await SaveAndPushFetalHeartRateAsync(heartRate, commonPHR!, upperAlarmThreshold, lowerAlarmThreshold, phrValue, sampleTimeFHR, normalPhrStatStartTime, normalPhrStatEndTime);
            heartRate.HeartRate = (int)phrValue;
            //await SaveAndPushFetalHeartRateEndFreqHeartRateAsync(heartRate, commonPHR!, upperAlarmThreshold, lowerAlarmThreshold, sampleTimeFHR, normalPhrStatStartTime, normalPhrStatEndTime);
            
        
        }
        */
        
        
        /// <summary>
        /// 延时计算
        /// </summary>
        /// <param name="heartRate"></param>
        /// <returns></returns>
        public async Task CalculateNormalFetalHeartRateScheduleAsync(HisGpsHeartRate heartRate)
        {
            var fhrScheduleKey = $"health_monitor/schedule_push/cal_normalphr_fetal_heart_rate/imei/{heartRate.Serialno}";

            DateTime nowInterval = DateTime.Now;
            if (nowInterval.Second > 0)
            {
                nowInterval = nowInterval.AddMinutes(1);
            }
            // 需要减去的分钟
            int minutesToSubtract = nowInterval.Minute % INTERVAL_FHR;
            var nextRunTime=nowInterval
                .AddMinutes(-minutesToSubtract)
                .AddMinutes(INTERVAL_FHR);
            TimeSpan timeUntilNextRun = nextRunTime - nowInterval;
            var ttl = (long)timeUntilNextRun.TotalSeconds;
            await SetIntervalTriggerAsync(fhrScheduleKey, heartRate.Serialno, ttl, heartRate);
        }

        /// <summary>
        ///
        /// </summary>
        /// <param name="heartRate"></param>
        /// <param name="commonPHR"></param>
        /// <param name="upperAlarmThreshold"></param>
        /// <param name="lowerAlarmThreshold"></param>
        /// <param name="phrValue"></param>
        /// <param name="sampleTime"></param>
        /// <param name="statStartTime"></param>
        /// <param name="statEndTime"></param>
        /// <returns></returns>
        private async Task SaveAndPushFetalHeartRateAsync(HisGpsHeartRate heartRate, PregnancyCommonHeartRateModel commonPHR, int upperAlarmThreshold, int lowerAlarmThreshold, double phrValue, string sampleTime, DateTime statStartTime, DateTime statEndTime)
        {
            // 计算胎心=孕妇心率*系数
            /**
            var fetalHeartRate = SafeType.SafeInt(phrValue * commonPHR?.StatModeAvgFprCoefficient!);
            fetalHeartRate = fetalHeartRate > 220 ? 220 : fetalHeartRate; // 胎心的最大值调整为220,超过都按该值220输出
            if (fetalHeartRate >= 220)
            {
                // 先使用最小系数计算
                var statMaxValueFprCoefficient = commonPHR?.StatMaxValueFprCoefficient!;
                var statMinValueFprCoefficient = commonPHR?.StatMinValueFprCoefficient!;
                var coefficient = statMaxValueFprCoefficient < statMinValueFprCoefficient ? statMaxValueFprCoefficient : statMinValueFprCoefficient;
                fetalHeartRate = SafeType.SafeInt(phrValue * coefficient);
                if (fetalHeartRate < 220)
                {
                    _logger.LogWarning($"{heartRate.Serialno} 使用极值系数 {coefficient} ,建模数据可能出现异常,请检查");
                }
                else
                {
                    fetalHeartRate = 220;
                    _logger.LogWarning($"{heartRate.Serialno} 使用所有系数都不能放映实际,建模数据可能出现异常,请检查");
                }
            }
            */

            #region  胎心系数使用基于心率与中位数对比
            var coefficient = 0f;
            // 孕妇心率少于中位数,取StatMinValueFprCoefficient
            if (heartRate.HeartRate < commonPHR!.Mode)
            {
                coefficient = commonPHR.StatMinValueFprCoefficient!;
                _logger.LogInformation($"{heartRate.Serialno} 孕妇心率少于中位数,使用最小值系数 {coefficient}");
            }
            // 孕妇心率大于中位数,取StatMaxValueFprCoefficient与StatModeAvgFprCoefficient中少的那个
            else if (heartRate.HeartRate > commonPHR.Mode)
            {
                if (commonPHR.StatModeAvgFprCoefficient > commonPHR.StatMaxValueFprCoefficient)
                {
                    coefficient = commonPHR.StatMaxValueFprCoefficient!;
                    _logger.LogInformation($"{heartRate.Serialno} 孕妇心率大于中位数,使用最大值系数 {coefficient}");
                }
                else
                {
                    coefficient = commonPHR.StatModeAvgFprCoefficient!;
                    _logger.LogInformation($"{heartRate.Serialno} 孕妇心率大于中位数,使用均值系数 {coefficient}");
                }
            }
            else
            {
                coefficient = commonPHR.StatModeAvgFprCoefficient;
                _logger.LogInformation($"{heartRate.Serialno} 孕妇心率等于中位数,使用均值系数 {coefficient}");
            }
            #endregion

            var fetalHeartRate = SafeType.SafeInt(phrValue * coefficient);
            // 胎心的最大值调整为220,超过都按该值220输出
           // fetalHeartRate = fetalHeartRate>= 220 ? 220 : fetalHeartRate;

            if (fetalHeartRate > 220)
            {
                fetalHeartRate = 220;
                _logger.LogWarning($"{heartRate.Serialno} 大于220,按220输出,计算因子:孕妇心率 {heartRate.HeartRate},系数 {coefficient},周期 周期:{statStartTime.ToString("yyyy-MM-dd HH:mm:ss")}----{statEndTime.ToString("yyyy-MM-dd HH:mm:ss")}");
            }

            // 胎心的最小值调整为90,超过都按该值90
            if (fetalHeartRate < 90)
            {
                fetalHeartRate = 90;
                _logger.LogWarning($"{heartRate.Serialno} 小于90,按90输出,计算因子:孕妇心率 {heartRate.HeartRate},系数 {coefficient},周期 周期:{statStartTime.ToString("yyyy-MM-dd HH:mm:ss")}----{statEndTime.ToString("yyyy-MM-dd HH:mm:ss")}");
            }


            var isAbnormal = fetalHeartRate > upperAlarmThreshold ? 1 : (fetalHeartRate < lowerAlarmThreshold ? 2 : 0);
            var phrFreqstatus = await _deviceCacheMgr.GetPregnancyHeartRateFreqStatusAsync(heartRate.Serialno);
            if (phrFreqstatus == null) isAbnormal = 0;
            var statsusDesc = (phrFreqstatus == null) ? "常规" : "高频";
            _logger.LogInformation($"{heartRate.Serialno} 在 {statsusDesc} 状态,生成胎心值:{fetalHeartRate},统计周期:{statStartTime.ToString("yyyy-MM-dd HH:mm:ss")}----{statEndTime.ToString("yyyy-MM-dd HH:mm:ss")}");
            //if (!isFreq)
            //{
            //    statStartTime = heartRate.LastUpdate;
            //    
            //} 
            // 保存到 数据服务 MySQL 数据库
            HisGpsFetalHeartRate gpsFetalHeartRate = new()
            {
                FetalHeartRateId = Guid.NewGuid().ToString("D"),
                PersonId = commonPHR!.PersonId,
                Serialno = heartRate.Serialno,
                HeartRate = fetalHeartRate,
                SampleTime = sampleTime.Length > 10 ? sampleTime.Substring(0, 10) : sampleTime,
                IsAbnormal = isAbnormal,
                StatStartTime = statStartTime,
                StatEndTime = statEndTime,//commonPHR.StatEndTime,
                CreateTime = DateTime.Now,
                Method = 1,
                IsDisplay = 1,
                DeviceKey = commonPHR!.DeviceKey
            };
            await _hisFetalHeartApiClient.AddAsync(gpsFetalHeartRate).ConfigureAwait(false);

            // 推送到api/v1/open/OpenIot/SetFetalHeartRateConfig
            // 推送最后一条常规心率计算的胎心数据到iot设备
            #region 推送最后一条常规心率计算的胎心数据到iot设备

            // 高频(<=12)-常规
            var lastPhr = await _serviceTDengine.GetLastAsync<PregnancyHeartRateModel>(heartRate.Serialno);
            if (lastPhr.MessageId == heartRate.MessageId && phrFreqstatus == null)
            {
                await _serviceIotApi.SetFetalHeartRateConfig(heartRate.Serialno, fetalHeartRate, sampleTime, isAbnormal);
                _logger.LogInformation($"{heartRate.Serialno} 推送最后一条常规心率计算的胎心数据到iot设备,高频(<=12)-常规");
            }
            // 高频(13)-常规-高频(13)
            if (phrFreqstatus != null)
            {
                var phr = await _serviceTDengine.GetBySerialNoAsync<PregnancyHeartRateModel>(heartRate.Serialno, 1);
                phr = phr.OrderByDescending(i => i.LastUpdate).ToList();
                // 获取高频数据
                var freqCollection = new List<PregnancyHeartRateModel>();
                PregnancyHeartRateModel? previousItem = null;
                foreach (var item in phr)
                {
                    if (previousItem != null)
                    {
                        var timeNextDiff = (previousItem!.LastUpdate - item.LastUpdate).TotalSeconds;
                        if (timeNextDiff <= 60)
                        {
                            freqCollection.Add(item);
                        }
                    }
                    // 高频最后一条
                    if (lastPhr.MessageId == item.MessageId)
                    {
                        freqCollection.Add(item);
                    }

                    previousItem = item;
                }
                //去除高频
                foreach (var item in freqCollection)
                {
                    phr.Remove(item);
                }
                lastPhr = phr.FirstOrDefault();
                if (lastPhr?.MessageId == heartRate.MessageId)
                {
                    await _serviceIotApi.SetFetalHeartRateConfig(heartRate.Serialno, fetalHeartRate, sampleTime, isAbnormal);
                    _logger.LogInformation($"{heartRate.Serialno} 推送最后一条常规心率计算的胎心数据到iot设备,高频(13)-常规-高频(13)");
                }
            }

            #endregion

            #region 高频心率计算胎心数据到iot设备
            // 高频(17) ,连续12个高频正常,也不停止且数据偏高和偏低也推送到iot
            if (phrFreqstatus != null && isAbnormal!=0) 
            {
                await _serviceIotApi.SetFetalHeartRateConfig(heartRate.Serialno, fetalHeartRate, sampleTime, isAbnormal);
            }
            #endregion
            var device = await _deviceCacheMgr.GetDeviceBySerialNoAsync(heartRate.Serialno).ConfigureAwait(false);
            var fhrMsgId = $"{heartRate.Serialno}-{sampleTime}-{Guid.NewGuid().ToString("D")[^3..]}";
            var fhrMsgTime = DateTimeUtil.GetDateTimeFromUnixTimeMilliseconds(long.Parse(sampleTime.Length < 13 ? sampleTime.PadRight(13, '0') : sampleTime)).ToString("yyyy-MM-dd HH:mm:ss");
            // 胎心数据推送到第三方
            var topic = "topic.push.third";
            var fhrThridMsg = new
            {
                messageId = fhrMsgId,
                topic = topic,
                time = fhrMsgTime,
                data = new
                {
                    imei = heartRate.Serialno,
                    value = fetalHeartRate,
                    isAbnormal,
                    type = "fetalHeart"
                }
            };
            await _serviceMqProcess.ProcessIMEIEventMessageAsync(fhrMsgId, topic, 31, fhrThridMsg).ConfigureAwait(false);

            // 胎心数据推送到微信
            if (isAbnormal != 0)
            {

                topic = "topic.push.wx";
                var fhrMsg = new
                {
                    messageId = fhrMsgId,
                    topic = topic,
                    time = fhrMsgTime,
                    data = new
                    {
                        deviceId = device?.DeviceId,
                        imei = heartRate.Serialno,
                        alarmTypeId = 12,
                        alarmDeviceName = heartRate.Serialno,
                        alarmRemarks = JsonConvert.SerializeObject(new { fetalHeartValue = fetalHeartRate, isAbnormal = isAbnormal }),
                        address = string.Empty,
                        deviceKey = device?.DeviceId
                    }
                };
                await _serviceMqProcess.ProcessIMEIEventMessageAsync(fhrMsgId, topic, fhrMsg).ConfigureAwait(false);

            }
        }


        private async Task SaveAndPushFetalHeartRateEndFreqHeartRateAsync(HisGpsHeartRate heartRate, PregnancyCommonHeartRateModel commonPHR, int upperAlarmThreshold, int lowerAlarmThreshold, string sampleTime, DateTime statStartTime, DateTime statEndTime)
        {
            // 计算胎心=孕妇心率*系数
            /**
            var fetalHeartRate = SafeType.SafeInt(phrValue * commonPHR?.StatModeAvgFprCoefficient!);
            fetalHeartRate = fetalHeartRate > 220 ? 220 : fetalHeartRate; // 胎心的最大值调整为220,超过都按该值220输出
            if (fetalHeartRate >= 220)
            {
                // 先使用最小系数计算
                var statMaxValueFprCoefficient = commonPHR?.StatMaxValueFprCoefficient!;
                var statMinValueFprCoefficient = commonPHR?.StatMinValueFprCoefficient!;
                var coefficient = statMaxValueFprCoefficient < statMinValueFprCoefficient ? statMaxValueFprCoefficient : statMinValueFprCoefficient;
                fetalHeartRate = SafeType.SafeInt(phrValue * coefficient);
                if (fetalHeartRate < 220)
                {
                    _logger.LogWarning($"{heartRate.Serialno} 使用极值系数 {coefficient} ,建模数据可能出现异常,请检查");
                }
                else
                {
                    fetalHeartRate = 220;
                    _logger.LogWarning($"{heartRate.Serialno} 使用所有系数都不能放映实际,建模数据可能出现异常,请检查");
                }
            }
            */

            #region  胎心系数使用基于心率与中位数对比
            var coefficient = 0f;
            // 孕妇心率少于中位数,取StatMinValueFprCoefficient
            if (heartRate.HeartRate < commonPHR!.Mode)
            {
                coefficient = commonPHR.StatMinValueFprCoefficient!;
                _logger.LogInformation($"{heartRate.Serialno} 孕妇心率少于中位数,使用最小值系数 {coefficient}");
            }
            // 孕妇心率大于中位数,取StatMaxValueFprCoefficient与StatModeAvgFprCoefficient中少的那个
            else if (heartRate.HeartRate > commonPHR.Mode)
            {
                if (commonPHR.StatModeAvgFprCoefficient > commonPHR.StatMaxValueFprCoefficient)
                {
                    coefficient = commonPHR.StatMaxValueFprCoefficient!;
                    _logger.LogInformation($"{heartRate.Serialno} 孕妇心率大于中位数,使用最大值系数 {coefficient}");
                }
                else
                {
                    coefficient = commonPHR.StatModeAvgFprCoefficient!;
                    _logger.LogInformation($"{heartRate.Serialno} 孕妇心率大于中位数,使用均值系数 {coefficient}");
                }
            }
            else
            {
                coefficient = commonPHR.StatModeAvgFprCoefficient;
                _logger.LogInformation($"{heartRate.Serialno} 孕妇心率等于中位数,使用均值系数 {coefficient}");
            }
            #endregion

            var fetalHeartRate = SafeType.SafeInt(heartRate.HeartRate! * coefficient);
            // 胎心的最大值调整为220,超过都按该值220输出
            // fetalHeartRate = fetalHeartRate>= 220 ? 220 : fetalHeartRate;

            if (fetalHeartRate > 220)
            {
                fetalHeartRate = 220;
                _logger.LogWarning($"{heartRate.Serialno} 大于220,按220输出,计算因子:孕妇心率 {heartRate.HeartRate},系数 {coefficient},周期 周期:{statStartTime.ToString("yyyy-MM-dd HH:mm:ss")}----{statEndTime.ToString("yyyy-MM-dd HH:mm:ss")}");
            }

            // 胎心的最小值调整为90,超过都按该值90
            if (fetalHeartRate < 90)
            {
                fetalHeartRate = 90;
                _logger.LogWarning($"{heartRate.Serialno} 小于90,按90输出,计算因子:孕妇心率 {heartRate.HeartRate},系数 {coefficient},周期 周期:{statStartTime.ToString("yyyy-MM-dd HH:mm:ss")}----{statEndTime.ToString("yyyy-MM-dd HH:mm:ss")}");
            }


            var isAbnormal = fetalHeartRate > upperAlarmThreshold ? 1 : (fetalHeartRate < lowerAlarmThreshold ? 2 : 0);
            var phrFreqstatus = await _deviceCacheMgr.GetPregnancyHeartRateFreqStatusAsync(heartRate.Serialno);
            if (phrFreqstatus == null) isAbnormal = 0;
            var statsusDesc = (phrFreqstatus == null) ? "常规" : "高频";
            _logger.LogInformation($"{heartRate.Serialno} 在 {statsusDesc} 状态,生成胎心值:{fetalHeartRate},统计周期:{statStartTime.ToString("yyyy-MM-dd HH:mm:ss")}----{statEndTime.ToString("yyyy-MM-dd HH:mm:ss")}");
            //if (!isFreq)
            //{
            //    statStartTime = heartRate.LastUpdate;
            //    
            //} 
            // 保存到 数据服务 MySQL 数据库
            HisGpsFetalHeartRate gpsFetalHeartRate = new()
            {
                FetalHeartRateId = Guid.NewGuid().ToString("D"),
                PersonId = commonPHR!.PersonId,
                Serialno = heartRate.Serialno,
                HeartRate = fetalHeartRate,
                SampleTime = sampleTime.Length > 10 ? sampleTime.Substring(0, 10) : sampleTime,
                IsAbnormal = isAbnormal,
                StatStartTime = statStartTime,
                StatEndTime = statEndTime,//commonPHR.StatEndTime,
                CreateTime = DateTime.Now,
                Method = 1,
                IsDisplay = 1,
                DeviceKey = commonPHR!.DeviceKey
            };
            await _hisFetalHeartApiClient.AddAsync(gpsFetalHeartRate).ConfigureAwait(false);

            // 推送到api/v1/open/OpenIot/SetFetalHeartRateConfig
            // 推送最后一条常规心率计算的胎心数据到iot设备
            #region 推送最后一条常规心率计算的胎心数据到iot设备

            // 高频(<=12)-常规
            var lastPhr = await _serviceTDengine.GetLastAsync<PregnancyHeartRateModel>(heartRate.Serialno);
            if (lastPhr.MessageId == heartRate.MessageId && phrFreqstatus == null)
            {
                await _serviceIotApi.SetFetalHeartRateConfig(heartRate.Serialno, fetalHeartRate, sampleTime, isAbnormal);
                _logger.LogInformation($"{heartRate.Serialno} 推送最后一条常规心率计算的胎心数据到iot设备,高频(<=12)-常规");
            }
            // 高频(13)-常规-高频(13)
            if (phrFreqstatus != null)
            {
                var phr = await _serviceTDengine.GetBySerialNoAsync<PregnancyHeartRateModel>(heartRate.Serialno, 1);
                phr = phr.OrderByDescending(i => i.LastUpdate).ToList();
                // 获取高频数据
                var freqCollection = new List<PregnancyHeartRateModel>();
                PregnancyHeartRateModel? previousItem = null;
                foreach (var item in phr)
                {
                    if (previousItem != null)
                    {
                        var timeNextDiff = (previousItem!.LastUpdate - item.LastUpdate).TotalSeconds;
                        if (timeNextDiff <= 60)
                        {
                            freqCollection.Add(item);
                        }
                    }
                    // 高频最后一条
                    if (lastPhr.MessageId == item.MessageId)
                    {
                        freqCollection.Add(item);
                    }

                    previousItem = item;
                }
                //去除高频
                foreach (var item in freqCollection)
                {
                    phr.Remove(item);
                }
                lastPhr = phr.FirstOrDefault();
                if (lastPhr?.MessageId == heartRate.MessageId)
                {
                    await _serviceIotApi.SetFetalHeartRateConfig(heartRate.Serialno, fetalHeartRate, sampleTime, isAbnormal);
                    _logger.LogInformation($"{heartRate.Serialno} 推送最后一条常规心率计算的胎心数据到iot设备,高频(13)-常规-高频(13)");
                }
            }

            #endregion

            #region 高频心率计算胎心数据到iot设备
            // 高频(17) ,连续12个高频正常,也不停止且数据偏高和偏低也推送到iot
            if (phrFreqstatus != null && isAbnormal != 0)
            {
                await _serviceIotApi.SetFetalHeartRateConfig(heartRate.Serialno, fetalHeartRate, sampleTime, isAbnormal);
            }
            #endregion
            var device = await _deviceCacheMgr.GetDeviceBySerialNoAsync(heartRate.Serialno).ConfigureAwait(false);
            var fhrMsgId = $"{heartRate.Serialno}-{sampleTime}-{Guid.NewGuid().ToString("D")[^3..]}";
            var fhrMsgTime = DateTimeUtil.GetDateTimeFromUnixTimeMilliseconds(long.Parse(sampleTime.Length < 13 ? sampleTime.PadRight(13, '0') : sampleTime)).ToString("yyyy-MM-dd HH:mm:ss");
            // 胎心数据推送到第三方
            var topic = "topic.push.third";
            var fhrThridMsg = new
            {
                messageId = fhrMsgId,
                topic = topic,
                time = fhrMsgTime,
                data = new
                {
                    imei = heartRate.Serialno,
                    value = fetalHeartRate,
                    isAbnormal,
                    type = "fetalHeart"
                }
            };
            await _serviceMqProcess.ProcessIMEIEventMessageAsync(fhrMsgId, topic, 31, fhrThridMsg).ConfigureAwait(false);

            // 胎心数据推送到微信
            if (isAbnormal != 0)
            {

                topic = "topic.push.wx";
                var fhrMsg = new
                {
                    messageId = fhrMsgId,
                    topic = topic,
                    time = fhrMsgTime,
                    data = new
                    {
                        deviceId = device?.DeviceId,
                        imei = heartRate.Serialno,
                        alarmTypeId = 12,
                        alarmDeviceName = heartRate.Serialno,
                        alarmRemarks = JsonConvert.SerializeObject(new { fetalHeartValue = fetalHeartRate, isAbnormal = isAbnormal }),
                        address = string.Empty,
                        deviceKey = device?.DeviceId
                    }
                };
                await _serviceMqProcess.ProcessIMEIEventMessageAsync(fhrMsgId, topic, fhrMsg).ConfigureAwait(false);

            }
        }

        private async Task SaveAndPushFetalHeartRateEndFreqHeartRateAsync(HisGpsHeartRate heartRate, PregnancyCommonHeartRateModel commonPHR, int highFreqSampleTimes, int upperAlarmThreshold, int lowerAlarmThreshold, string sampleTime, DateTime statStartTime, DateTime statEndTime)
        {
            // 计算胎心=孕妇心率*系数

            #region  胎心系数使用基于心率与中位数对比
            var coefficient = 0f;
            // 孕妇心率少于中位数,取StatMinValueFprCoefficient
            if (heartRate.HeartRate < commonPHR!.Mode)
            {
                coefficient = commonPHR.StatMinValueFprCoefficient!;
                _logger.LogInformation($"{heartRate.Serialno} 孕妇心率少于中位数,使用最小值系数 {coefficient}");
            }
            // 孕妇心率大于中位数,取StatMaxValueFprCoefficient与StatModeAvgFprCoefficient中少的那个
            else if (heartRate.HeartRate > commonPHR.Mode)
            {
                if (commonPHR.StatModeAvgFprCoefficient > commonPHR.StatMaxValueFprCoefficient)
                {
                    coefficient = commonPHR.StatMaxValueFprCoefficient!;
                    _logger.LogInformation($"{heartRate.Serialno} 孕妇心率大于中位数,使用最大值系数 {coefficient}");
                }
                else
                {
                    coefficient = commonPHR.StatModeAvgFprCoefficient!;
                    _logger.LogInformation($"{heartRate.Serialno} 孕妇心率大于中位数,使用均值系数 {coefficient}");
                }
            }
            else
            {
                coefficient = commonPHR.StatModeAvgFprCoefficient;
                _logger.LogInformation($"{heartRate.Serialno} 孕妇心率等于中位数,使用均值系数 {coefficient}");
            }
            #endregion

            var fetalHeartRate = SafeType.SafeInt(heartRate.HeartRate! * coefficient);
            // 胎心的最大值调整为220,超过都按该值220输出
            // fetalHeartRate = fetalHeartRate>= 220 ? 220 : fetalHeartRate;

            var phrFreqstatus = await _deviceCacheMgr.GetPregnancyHeartRateFreqStatusAsync(heartRate.Serialno);

            #region 判断是否够highFreqSampleTimes,540s
            var ts = DateTimeUtil.GetTimeDifferenceInSeconds((DateTime)heartRate.LastUpdate!, phrFreqstatus!.LastUpdate);
            // 判断是否够highFreqSampleTimes,540s
            ///高频时长不足10分钟停止高频的胎心值生成说明:最近12个数据的最小值生成胎心值,
            ///对于小于高频下限阀值取高频下限阀值进行转换;
            ///对于高于高频上限阀值取高频上限阀值进行转换。并输出相关日志后续进行数据分析。
            if (ts < highFreqSampleTimes)
            {
                if (fetalHeartRate > upperAlarmThreshold)
                {
                    _logger.LogWarning($"{heartRate.Serialno} 高频持续不足10分钟,计算胎心值 {fetalHeartRate} 高于高频警告上限阀值{upperAlarmThreshold},最后胎心值{upperAlarmThreshold}");
                    fetalHeartRate = upperAlarmThreshold;

                }
                else if (fetalHeartRate < lowerAlarmThreshold)
                {
                    _logger.LogWarning($"{heartRate.Serialno} 高频持续不足10分钟,计算胎心值 {fetalHeartRate} 低于高频警告下限阀值 {lowerAlarmThreshold},最后胎心值{lowerAlarmThreshold}");
                    fetalHeartRate = lowerAlarmThreshold;
                }
                else
                {
                    _logger.LogWarning($"{heartRate.Serialno} 高频持续不足10分钟,在高频警告下限阀值 {lowerAlarmThreshold} 和 高频警告上限阀值:{upperAlarmThreshold}之间,最后胎心值{fetalHeartRate}");
                }
            }
            // 超过highFreqSampleTimes,540s
            else
            {
                if (fetalHeartRate > 220)
                {
                    fetalHeartRate = 220;
                    _logger.LogWarning($"{heartRate.Serialno} 大于220,按220输出,计算因子:孕妇心率 {heartRate.HeartRate},系数 {coefficient},周期 周期:{statStartTime.ToString("yyyy-MM-dd HH:mm:ss")}----{statEndTime.ToString("yyyy-MM-dd HH:mm:ss")}");
                }

                // 胎心的最小值调整为90,超过都按该值90
                if (fetalHeartRate < 90)
                {
                    fetalHeartRate = 90;
                    _logger.LogWarning($"{heartRate.Serialno} 小于90,按90输出,计算因子:孕妇心率 {heartRate.HeartRate},系数 {coefficient},周期 周期:{statStartTime.ToString("yyyy-MM-dd HH:mm:ss")}----{statEndTime.ToString("yyyy-MM-dd HH:mm:ss")}");
                }

            }
            #endregion


            var isAbnormal = fetalHeartRate > upperAlarmThreshold ? 1 : (fetalHeartRate < lowerAlarmThreshold ? 2 : 0);
            if (phrFreqstatus == null) isAbnormal = 0;
            var statsusDesc = (phrFreqstatus == null) ? "常规" : "高频";
            _logger.LogInformation($"{heartRate.Serialno} 在 {statsusDesc} 状态,生成胎心值:{fetalHeartRate},统计周期:{statStartTime.ToString("yyyy-MM-dd HH:mm:ss")}----{statEndTime.ToString("yyyy-MM-dd HH:mm:ss")}");
            //if (!isFreq)
            //{
            //    statStartTime = heartRate.LastUpdate;
            //    
            //} 
            // 保存到 数据服务 MySQL 数据库
            HisGpsFetalHeartRate gpsFetalHeartRate = new()
            {
                FetalHeartRateId = Guid.NewGuid().ToString("D"),
                PersonId = commonPHR!.PersonId,
                Serialno = heartRate.Serialno,
                HeartRate = fetalHeartRate,
                SampleTime = sampleTime.Length > 10 ? sampleTime.Substring(0, 10) : sampleTime,
                IsAbnormal = isAbnormal,
                StatStartTime = statStartTime,
                StatEndTime = statEndTime,//commonPHR.StatEndTime,
                CreateTime = DateTime.Now,
                Method = 1,
                IsDisplay = 1,
                DeviceKey = commonPHR!.DeviceKey
            };
            await _hisFetalHeartApiClient.AddAsync(gpsFetalHeartRate).ConfigureAwait(false);

            // 推送到api/v1/open/OpenIot/SetFetalHeartRateConfig
            // 推送最后一条常规心率计算的胎心数据到iot设备
            #region 推送最后一条常规心率计算的胎心数据到iot设备

            // 高频(<=12)-常规
            var lastPhr = await _serviceTDengine.GetLastAsync<PregnancyHeartRateModel>(heartRate.Serialno);
            if (lastPhr.MessageId == heartRate.MessageId && phrFreqstatus == null)
            {
                await _serviceIotApi.SetFetalHeartRateConfig(heartRate.Serialno, fetalHeartRate, sampleTime, isAbnormal);
                _logger.LogInformation($"{heartRate.Serialno} 推送最后一条常规心率计算的胎心数据到iot设备,高频(<=12)-常规");
            }
            // 高频(13)-常规-高频(13)
            if (phrFreqstatus != null)
            {
                var phr = await _serviceTDengine.GetBySerialNoAsync<PregnancyHeartRateModel>(heartRate.Serialno, 1);
                phr = phr.OrderByDescending(i => i.LastUpdate).ToList();
                // 获取高频数据
                var freqCollection = new List<PregnancyHeartRateModel>();
                PregnancyHeartRateModel? previousItem = null;
                foreach (var item in phr)
                {
                    if (previousItem != null)
                    {
                        var timeNextDiff = (previousItem!.LastUpdate - item.LastUpdate).TotalSeconds;
                        if (timeNextDiff <= 60)
                        {
                            freqCollection.Add(item);
                        }
                    }
                    // 高频最后一条
                    if (lastPhr.MessageId == item.MessageId)
                    {
                        freqCollection.Add(item);
                    }

                    previousItem = item;
                }
                //去除高频
                foreach (var item in freqCollection)
                {
                    phr.Remove(item);
                }
                lastPhr = phr.FirstOrDefault();
                if (lastPhr?.MessageId == heartRate.MessageId)
                {
                    await _serviceIotApi.SetFetalHeartRateConfig(heartRate.Serialno, fetalHeartRate, sampleTime, isAbnormal);
                    _logger.LogInformation($"{heartRate.Serialno} 推送最后一条常规心率计算的胎心数据到iot设备,高频(13)-常规-高频(13)");
                }
            }

            #endregion

            #region 高频心率计算胎心数据到iot设备
            // 高频(17) ,连续12个高频正常,也不停止且数据偏高和偏低也推送到iot
            if (phrFreqstatus != null && isAbnormal != 0)
            {
                await _serviceIotApi.SetFetalHeartRateConfig(heartRate.Serialno, fetalHeartRate, sampleTime, isAbnormal);
            }
            #endregion
            var device = await _deviceCacheMgr.GetDeviceBySerialNoAsync(heartRate.Serialno).ConfigureAwait(false);
            var fhrMsgId = $"{heartRate.Serialno}-{sampleTime}-{Guid.NewGuid().ToString("D")[^3..]}";
            var fhrMsgTime = DateTimeUtil.GetDateTimeFromUnixTimeMilliseconds(long.Parse(sampleTime.Length < 13 ? sampleTime.PadRight(13, '0') : sampleTime)).ToString("yyyy-MM-dd HH:mm:ss");
            // 胎心数据推送到第三方
            var topic = "topic.push.third";
            var fhrThridMsg = new
            {
                messageId = fhrMsgId,
                topic = topic,
                time = fhrMsgTime,
                data = new
                {
                    imei = heartRate.Serialno,
                    value = fetalHeartRate,
                    isAbnormal,
                    type = "fetalHeart"
                }
            };
            await _serviceMqProcess.ProcessIMEIEventMessageAsync(fhrMsgId, topic, 31, fhrThridMsg).ConfigureAwait(false);

            // 胎心数据推送到微信
            if (isAbnormal != 0)
            {

                topic = "topic.push.wx";
                var fhrMsg = new
                {
                    messageId = fhrMsgId,
                    topic = topic,
                    time = fhrMsgTime,
                    data = new
                    {
                        deviceId = device?.DeviceId,
                        imei = heartRate.Serialno,
                        alarmTypeId = 12,
                        alarmDeviceName = heartRate.Serialno,
                        alarmRemarks = JsonConvert.SerializeObject(new { fetalHeartValue = fetalHeartRate, isAbnormal = isAbnormal }),
                        address = string.Empty,
                        deviceKey = device?.DeviceId
                    }
                };
                await _serviceMqProcess.ProcessIMEIEventMessageAsync(fhrMsgId, topic, fhrMsg).ConfigureAwait(false);

            }
        }

        private async Task SetIntervalTriggerAsync(string key, string imei, long interval, HisGpsHeartRate heartRate)
        {
            // var key = $"health_monitor/schedule_push/{type}/imei/{imei}";
            var schedulePush = await _serviceEtcd.GetValAsync(key).ConfigureAwait(false);
            if (string.IsNullOrWhiteSpace(schedulePush))
            {
                var now = DateTime.Now;
                var timeNextRun = now.Add(TimeSpan.FromSeconds(interval));
                var data = new
                {
                    imei,
                    create_time = now.ToString("yyyy-MM-dd HH:mm:ss"),
                    ttl = interval,
                    next_run_time = timeNextRun.ToString("yyyy-MM-dd HH:mm:ss"),
                    trigger = heartRate,

                };
                var result = JsonConvert.SerializeObject(data);
                await _serviceEtcd.PutValAsync(key, result, interval, false).ConfigureAwait(false);
            }
        }

        /// <summary>
        /// 高频延时计算触发器
        /// </summary>
        /// <param name="key"></param>
        /// <param name="imei"></param>
        /// <param name="interval"></param>
        /// <param name="heartRate"></param>
        /// <returns></returns>
        private async Task SetFreqHeartRateTriggerAsync(string key, string imei, long interval, HisGpsHeartRate? heartRate=null)
        {
            var schedulePush = await _serviceEtcd.GetValAsync(key).ConfigureAwait(false);
            if (string.IsNullOrWhiteSpace(schedulePush))
            {
                var now = DateTime.Now;
                var data = new
                {
                    imei,
                    create_time = now.ToString("yyyy-MM-dd HH:mm:ss"),
                    lease = interval,
                    trigger = heartRate,
                };
                var result = JsonConvert.SerializeObject(data);
                await _serviceEtcd.PutValAsync(key, result, interval, false).ConfigureAwait(false);
            }
            else 
            {
                await _serviceEtcd.PutValAsync(key, schedulePush, interval, false).ConfigureAwait(false);
            }

        }
        
        /// <summary>
        ///  去除高频数据
        /// </summary>
        /// <param name="phr"></param>
        /// <param name="highFreqSampleInterva"></param>
        /// <returns></returns>
        private static List<PregnancyHeartRateModel> GetNonFreqPregnancyHeartRate(List<PregnancyHeartRateModel> phr,int highFreqSampleInterval)
        {
            //phr = phr.OrderByDescending(i => i.LastUpdate).ToList();
            //var result = new List<PregnancyHeartRateModel>();
            //PregnancyHeartRateModel? previousItem = null;

            //foreach (var item in phr)
            //{
            //    if (previousItem != null)
            //    {
            //        var timeNextDiff =(previousItem!.LastUpdate - item.LastUpdate).TotalSeconds;
            //        if (timeNextDiff > highFreqSampleInterval)
            //        {
            //            result.Add(previousItem);
            //        }
            //    }
            //    previousItem = item;
            //}

            //// 添加上一个
            //if (previousItem != null)
            //{
            //    result.Add(previousItem);
            //}

            //return result;

            #region 反向
            var phr1 = phr.OrderByDescending(i => i.LastUpdate).ToList();
            var result = new List<PregnancyHeartRateModel>();
            PregnancyHeartRateModel? previousItem1 = null;

            foreach (var item in phr1)
            {
                if (previousItem1 != null)
                {
                    var timeNextDiff = (previousItem1!.LastUpdate - item.LastUpdate).TotalSeconds;
                    if (timeNextDiff > highFreqSampleInterval)
                    {
                        result.Add(previousItem1);
                    }
                }
                previousItem1 = item;
            }

            // 添加上一个
            if (previousItem1 != null)
            {
                result.Add(previousItem1);
            }
            #endregion

            #region 正向
            var phr2 = phr.OrderByDescending(i => i.LastUpdate).ToList(); ;
            var freqCollection = new List<PregnancyHeartRateModel>();
            PregnancyHeartRateModel? previousItem = null;
            foreach (var item in phr2)
            {
                if (previousItem != null)
                {
                    var timeNextDiff = (previousItem!.LastUpdate - item.LastUpdate).TotalSeconds;
                    if (timeNextDiff <= highFreqSampleInterval)
                    {
                        freqCollection.Add(item);
                    }
                }
                previousItem = item;
            }
            //去除高频
            foreach (var item in freqCollection)
            {
                phr2.Remove(item);
            }
            #endregion

            // 交集
            var commonElements = phr2.Intersect(result).ToList();
            return commonElements;
        }

        /// <summary>
        /// 获取高频数据
        /// </summary>
        /// <param name="phr"></param>
        /// <param name="highFreqSampleInterval"></param>
        /// <returns></returns>
        private static List<PregnancyHeartRateModel> GetFreqPregnancyHeartRate(List<PregnancyHeartRateModel> phr, int highFreqSampleInterval)
        {
            phr = phr.OrderByDescending(i => i.LastUpdate).ToList();
            var freqCollection = new List<PregnancyHeartRateModel>();
            PregnancyHeartRateModel? previousItem = null;

            foreach (var item in phr)
            {
                if (previousItem != null)
                {
                    var timeNextDiff = (previousItem.LastUpdate - item.LastUpdate).TotalSeconds;
                    if (timeNextDiff <= highFreqSampleInterval)
                    {
                        freqCollection.Add(previousItem);
                    }
                }
                previousItem = item;
            }

            // 检查最后一条是否高频
            if (previousItem != null && (phr.Last().LastUpdate - previousItem.LastUpdate).TotalSeconds <= highFreqSampleInterval)
            {
                freqCollection.Add(previousItem);
            }

            return freqCollection;
        }

    }
}