using HealthMonitor.Model.Service.Mapper;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using TelpoDataService.Util.Clients;
using TelpoDataService.Util.Entities.GpsCard;
using TelpoDataService.Util.Entities.GpsLocationHistory;
using TelpoDataService.Util.Models;
using TelpoDataService.Util.QueryObjects;
using HealthMonitor.Common;

namespace HealthMonitor.Service.Cache
{
    public class DeviceCacheManager
    {
        private readonly ILogger<DeviceCacheManager> _logger;
        private const string CACHE_KEY_DEVICE = "Device_";
        private const string CACHE_KEY_GPSDEVICE_WATCH_CONFIG = "#GPSDEVICE_WATCH_CONFIG_HASH";
        private const string CACHE_KEY_FETALMOVEMENT = "FM_";
        private const string CACHE_KEY_FETALHEARTRATE = "FHR_";
        private const string CACHE_KEY_PHRFREQSTATUS = "PhrFreqStatus_";

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




        public DeviceCacheManager(ILogger<DeviceCacheManager> logger
            , GpsLocationHistoryAccessorClient<HisGpsFetalMovement> hisFetalMovementApiClient
            , GpsLocationHistoryAccessorClient<HisGpsFetalHeartRate> hisFetalHeartRateApiClient)
        {
            _logger = logger;
            _hisFetalMovementApiClient = hisFetalMovementApiClient;
            _hisFetalHeartRateApiClient = hisFetalHeartRateApiClient;
        }

        /// <summary>
        /// 获取device_id
        /// </summary>
        /// <param name="sn"></param>
        /// <returns></returns>
        public async Task<GpsDevice?> GetDeviceBySerialNoAsync(string sn)
        {
            string key = CACHE_KEY_DEVICE + sn;
            var device = await RedisHelperDb10.GetAsync<GpsDevice>(key).ConfigureAwait(false);
            return device;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sn"></param>
        /// <param name="bizCode">
        /// 业务码
        /// 0067 胎心启动配置
        /// </param>
        /// <returns></returns>
        public async Task<JObject?> GetGpsDeviceWatchConfigCacheObjectBySerialNoAsync(string sn, string bizCode)
        {
            if (string.IsNullOrWhiteSpace(sn)) return null;

            try
            {
                var config = await RedisHelperDb7.HGetAsync(CACHE_KEY_GPSDEVICE_WATCH_CONFIG, $"{sn}_{bizCode}").ConfigureAwait(false);

                if (config == null) return null;
                _logger.LogInformation($"{sn} 配置信息 {config}");
                return (JObject)JsonConvert.DeserializeObject(config)!;
            }
            catch (Exception ex)
            {
                _logger.LogWarning($"Redis DB7发生异常:{ex.Message}, {ex.StackTrace}");
            }

            return null;
        }


        #region 心率相关
        /// <summary>
        ///  读取高频状态
        /// </summary>
        /// <param name="sn"></param>
        /// <returns></returns>
        public async Task<PregnancyHeartRateModel?> GetPregnancyHeartRateFreqStatusAsync(string sn)
        {
            try
            {
                var key = CACHE_KEY_PHRFREQSTATUS+sn;
                var status = await RedisHelper.GetAsync(key).ConfigureAwait(false);
                if (string.IsNullOrEmpty(status)) return null;
                return JsonConvert.DeserializeObject<PregnancyHeartRateModel>(status);
            }
            catch (Exception ex)
            {
                _logger.LogWarning($"Redis 发生异常:{ex.Message}, {ex.StackTrace}");
            }
            return null;
        }

        public async Task SetPregnancyHeartRateFreqStatusAsync(string sn, PregnancyHeartRateModel status,int expire=-1)
        {
            try
            {
                var key = CACHE_KEY_PHRFREQSTATUS + sn;
                var data=JsonConvert.SerializeObject(status);
                await RedisHelper.SetAsync(key, data, expire).ConfigureAwait(false);
            }
            catch (Exception ex)
            {
                _logger.LogWarning($"Redis 发生异常:{ex.Message}, {ex.StackTrace}");
            }
        }

        public async Task DelPregnancyHeartRateFreqStatusAsync(string sn)
        {
            try
            {
                var key = CACHE_KEY_PHRFREQSTATUS + sn;
                await RedisHelper.DelAsync(key).ConfigureAwait(false);
            }
            catch (Exception ex)
            {
                _logger.LogWarning($"Redis 发生异常:{ex.Message}, {ex.StackTrace}");
            }
            
        }

        public async Task SetFetalHeartRateAsync(string serialNo, string sampleTime)
        {
            try
            {
                var key = $"{CACHE_KEY_FETALHEARTRATE}_{serialNo}_{sampleTime}";
                var time = long.Parse(sampleTime.Length < 13 ? sampleTime.PadRight(13, '0') : sampleTime);
                var value = DateTimeUtil.GetDateTimeFromUnixTimeMilliseconds(time).ToString("yyyy-MM-dd HH:mm:ss");
                await RedisHelper.SetAsync(key, value, 7200).ConfigureAwait(false);
            }
            catch (Exception ex)
            {

                _logger.LogWarning($"Redis 发生异常:{ex.Message}, {ex.StackTrace}");
            }
        }

        public async Task<bool> FetalHeartRateIsExistedAsync(string serialNo, string sampleTime)
        {
            try
            {
                var key = $"{CACHE_KEY_FETALHEARTRATE}_{serialNo}_{sampleTime}";
                var res = await RedisHelper.GetAsync(key).ConfigureAwait(false);

                if (string.IsNullOrEmpty(res))
                {
                    GeneralParam param = new()
                    {
                        Filters = new List<QueryFilterCondition>
                        {
                            new ()
                            {
                                Key=nameof(HisGpsFetalHeartRate.Serialno),
                                Value=serialNo,
                                ValueType=QueryValueTypeEnum.String,
                                Operator=QueryOperatorEnum.Equal
                            },
                            new ()
                            {
                                Key=nameof(HisGpsFetalHeartRate.SampleTime),
                                Value=sampleTime,
                                ValueType=QueryValueTypeEnum.String,
                                Operator=QueryOperatorEnum.Equal
                            },
                        }
                    };
                    var isFetalMovementExist = await _hisFetalHeartRateApiClient.GetFirstAsync(param, serialNo[^2..], null, new RequestHeader { RequestId = Guid.NewGuid().ToString("D") });
                    if (isFetalMovementExist != null)
                    {
                        await SetFetalHeartRateAsync(serialNo, sampleTime);
                        return true;
                    }
                }
                else
                {
                    return true;
                }

            }
            catch (Exception ex)
            {
                _logger.LogWarning($"Redis 发生异常:{ex.Message}, {ex.StackTrace}");
            }
            return false;
        }

        #endregion

        #region 胎动相关
        public async Task SetFetalMovementAsync(string serialNo, string sampleTime, HisGpsFetalMovement fm)
        {
            try
            {
                var key = $"{CACHE_KEY_FETALMOVEMENT}_{serialNo}_{sampleTime}";
                var time = long.Parse(sampleTime.Length < 13 ? sampleTime.PadRight(13, '0') : sampleTime);
                var value = DateTimeUtil.GetDateTimeFromUnixTimeMilliseconds(time).ToString("yyyy-MM-dd HH:mm:ss");

                fm.SampleTime = value;

                await RedisHelper.SetAsync(key, JsonConvert.SerializeObject(fm), 7200).ConfigureAwait(false);
            }
            catch (Exception ex)
            {

                _logger.LogWarning($"Redis 发生异常:{ex.Message}, {ex.StackTrace}");
            }
        }

        public async Task<bool> FetalMovementIsExistedAsync(string serialNo, string sampleTime)
        {
            try
            {
                var key = $"{CACHE_KEY_FETALMOVEMENT}_{serialNo}_{sampleTime}";
                var res = await RedisHelper.GetAsync(key).ConfigureAwait(false);

                if (string.IsNullOrEmpty(res))
                {
                    GeneralParam param = new()
                    {
                        Filters = new List<QueryFilterCondition>
                        {
                            new ()
                            {
                                Key=nameof(HisGpsFetalMovement.Serialno),
                                Value=serialNo,
                                ValueType=QueryValueTypeEnum.String,
                                Operator=QueryOperatorEnum.Equal
                            },
                            new ()
                            {
                                Key=nameof(HisGpsFetalMovement.SampleTime),
                                Value=sampleTime,
                                ValueType=QueryValueTypeEnum.String,
                                Operator=QueryOperatorEnum.Equal
                            },
                        }
                    };
                    var isFetalMovementExist = await _hisFetalMovementApiClient.GetFirstAsync(param, serialNo[^2..], null, new RequestHeader { RequestId = Guid.NewGuid().ToString("D") });
                    if (isFetalMovementExist != null)
                    {
                        await SetFetalMovementAsync(serialNo, sampleTime, isFetalMovementExist);
                        return true;
                    }
                }
                else
                {
                    return true;
                }

            }
            catch (Exception ex)
            {
                _logger.LogWarning($"Redis 发生异常:{ex.Message}, {ex.StackTrace}");
            }
            return false;
        }
        #endregion

        #region  业务间隔
        public async Task<string?> GetBizIntervalAsync(string sn, string biz)
        {
            try
            {
                var key = biz + "-"+sn;
                var status = await RedisHelper.GetAsync(key).ConfigureAwait(false);
                return status;
            }
            catch (Exception ex)
            {
                _logger.LogWarning($"Redis 发生异常:{ex.Message}, {ex.StackTrace}");
            }
            return null;
        }
        /// <summary>
        /// 业务间隔(默认15分钟)
        /// </summary>
        /// <param name="sn"></param>
        /// <param name="biz"></param>
        /// <param name="ttl"></param>
        /// <returns></returns>
        public async Task SetBizIntervalAsync(string sn, string biz, int ttl=60*15)
        {
            try
            {
                var key = biz + "-" + sn;
                await RedisHelper.SetAsync(key, biz, ttl).ConfigureAwait(false);
            }
            catch (Exception ex)
            {
                _logger.LogWarning($"Redis 发生异常:{ex.Message}, {ex.StackTrace}");
            }
        }

        #endregion
    }
}