using HealthMonitor.Common.helper;
using HealthMonitor.Model.Config;
using HealthMonitor.Service.Resolver;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using HealthMonitor.Model.Service;
using TelpoDataService.Util.Entities.GpsCard;
using TelpoDataService.Util;
using TelpoDataService.Util.Clients;
using TelpoDataService.Util.Models;
using TelpoDataService.Util.QueryObjects;
using HealthMonitor.Service.Cache;
using HealthMonitor.Model.Cache;
using Etcdserverpb;

namespace HealthMonitor.Service.Biz
{
    public class IotApiService
    {
        private readonly ServiceConfig _configService;
        private readonly ILogger<IotApiService> _logger;
        private readonly PersonCacheManager _personCacheMgr;
        private readonly DeviceCacheManager _deviceCacheMgr;


        private readonly HttpHelper _httpHelper = default!;

        private readonly GpsCardAccessorClient<GpsPerson> _gpsPersonApiClient;

        public IotApiService(ILogger<IotApiService> logger, HttpHelper httpHelper, DeviceCacheManager deviceCacheMgr, GpsCardAccessorClient<GpsPerson> gpsPersonApiClient, IOptions<ServiceConfig> optConfigService, PersonCacheManager personCacheMgr)
        {
            _configService = optConfigService.Value;
            _httpHelper=httpHelper; 
            _logger = logger;
            _personCacheMgr = personCacheMgr;
            _gpsPersonApiClient = gpsPersonApiClient;
            _deviceCacheMgr = deviceCacheMgr;
        }

        #region 平台下发血压标定参数
        /// <summary>
        /// 平台下发血压标定参数
        /// </summary>
        /// <param name="bpsCalibrationConfig"></param>
        /// <returns></returns>
        public async Task<bool> SetBloodPressCalibrationConfigAsync(BloodPressCalibrationConfigModel bpsCalibrationConfig)
        {

#if DEBUG
             var flag = true;
#else
            //systolicCalibrationValue = 0,  //收缩压标定值,值为0 表示不生效
            //diastolicCalibrationValue 0, //舒张压标定值,值为0表示不生效
            //systolicIncValue = 0, //收缩压显示增量,值为0 表示不生效
            //diastolicIncValue = 0   //舒张压显示增量,值为0 表示不生效

            var flag = false;
            try
            {
                var url = $"{_configService.IotWebApiUrl}Command/SetBloodPressCalibrationConfig";
                List<KeyValuePair<string, string>> headers = new()
                {
                    new KeyValuePair<string, string>("AuthKey", "key1")
                };
                var res = await _httpHelper.HttpToPostAsync(url, bpsCalibrationConfig, headers).ConfigureAwait(false);
                _logger.LogInformation($"向{bpsCalibrationConfig.Imei}下发增量值数据:{JsonConvert.SerializeObject(bpsCalibrationConfig)},响应:{res}");
                var resJToken = JsonConvert.DeserializeObject(res ?? string.Empty) as JToken;
                flag= resJToken?["message"]?.ToString().Equals("ok") ?? false;

            }
            catch (Exception ex)
            {
                _logger.LogError($"{nameof(SetBloodPressCalibrationConfigAsync)} 下发血压增量值异常:{ex.Message}, {ex.StackTrace}");

            }
           

#endif

            return flag;


        }


        public async Task<BloodPressCalibrationConfigModelReponse> SetBloodPressCalibrationConfig2Async(BloodPressCalibrationConfigModel bpsCalibrationConfig)
        {
            BloodPressCalibrationConfigModelReponse response = new BloodPressCalibrationConfigModelReponse();
            response.Flag = false;
            response.Message = string.Empty;
#if DEBUG
            //var flag = true;
            response.Flag=true;
#else
            //systolicCalibrationValue = 0,  //收缩压标定值,值为0 表示不生效
            //diastolicCalibrationValue 0, //舒张压标定值,值为0表示不生效
            //systolicIncValue = 0, //收缩压显示增量,值为0 表示不生效
            //diastolicIncValue = 0   //舒张压显示增量,值为0 表示不生效

            // var flag = false;
            try
            {
                var url = $"{_configService.IotWebApiUrl}Command/SetBloodPressCalibrationConfig";
                List<KeyValuePair<string, string>> headers = new()
                {
                    new KeyValuePair<string, string>("AuthKey", "key1")
                };
                var res = await _httpHelper.HttpToPostAsync(url, bpsCalibrationConfig, headers).ConfigureAwait(false);
                _logger.LogInformation($"向{bpsCalibrationConfig.Imei}下发增量值数据:{JsonConvert.SerializeObject(bpsCalibrationConfig)},响应:{res}");
                var resJToken = JsonConvert.DeserializeObject(res ?? string.Empty) as JToken;
                //response.Flag= resJToken?["message"]?.ToString().Equals("ok") ?? false;
                response.Flag = Convert.ToBoolean(resJToken?["succeed"]?.ToString());
                if (!response.Flag)
                {
                    response.Message = resJToken?["message"]?.ToString()!;
                }
            }
            catch (Exception ex)
            {
                _logger.LogError($"{nameof(SetBloodPressCalibrationConfigAsync)} 下发血压增量值异常:{ex.Message}, {ex.StackTrace}");

            }
           

#endif

            return response;
        }

        public async Task<bool> UpdatePersonRemarksAsync(string imei, int systolicRefValue, int diastolicRefValue, int systolicIncValue, int diastolicIncValue, string remarks = "is_blood_press")
        {
            var flag = false;
            try
            {

                // 保证实时性,先更新缓存,再更新数据库
                var personCache = await _personCacheMgr.GetDeviceGpsPersonCacheObjectBySerialNoAsync(new Guid().ToString(), imei).ConfigureAwait(false);

                if (personCache == null)
                {
                    _logger.LogInformation($"{imei} -- Person remarks数据异常,检查缓存和数据库");
                }
                else
                {
                    var newRemarkData = new
                    {
                        imei,
                        time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
                        commandValue = new
                        {
                            systolicCalibrationValue = systolicRefValue,  //收缩压标定值,值为0 表示不生效
                            diastolicCalibrationValue = diastolicRefValue, //舒张压标定值,值为0表示不生效
                            systolicIncValue, //收缩压显示增量,值为0 表示不生效
                            diastolicIncValue  //舒张压显示增量,值为0 表示不生效
                        }
                    };
                    var newRemarkStr = $"{remarks}:{JsonConvert.SerializeObject(newRemarkData)}|";

                    personCache["person"]!["remarks"] = newRemarkStr;
                    bool cacheFlag = await _personCacheMgr.UpdateDeviceGpsPersonCacheObjectBySerialNoAsync(personCache, imei);
                    if (cacheFlag)
                    {
                        GeneralParam condition = new()
                        {
                            Filters = new List<QueryFilterCondition> {
                            new QueryFilterCondition {
                                Key=nameof(GpsDevice.Serialno),
                                Value=imei,
                                Operator= QueryOperatorEnum.Equal,
                                ValueType=QueryValueTypeEnum.String
                            }
                        },
                            OrderBys = new List<OrderByCondition> { new OrderByCondition { Key = "serialno", IsDesc = true } }

                        };
                        _logger.LogInformation($"{imei} 更新缓存{nameof(UpdatePersonRemarksAsync)}成功,{JsonConvert.SerializeObject(personCache)}");
                        // 读取数据库
                        var person = await _gpsPersonApiClient.GetFirstAsync(condition, new RequestHeader() { RequestId = $"{imei}" }).ConfigureAwait(false);
                        // 更新字段
                        person!.Remarks = newRemarkStr;
                        await _gpsPersonApiClient.UpdateAsync(person, new RequestHeader() { RequestId = $"{imei}" }).ConfigureAwait(false);
                        _logger.LogInformation($"{imei} 更新Person remarks字段|{person.Remarks}");

                    }
                    else
                    {
                        _logger.LogInformation($"{imei} 更新缓存和数据库{nameof(UpdatePersonRemarksAsync)}失败,{JsonConvert.SerializeObject(personCache)}");
                    }
                    flag = cacheFlag;
                }
                // else if (string.IsNullOrWhiteSpace(personCache["person"]!["remarks"]!.ToString()))
                //else if (personCache?["person"]!["remarks"]!.ToString()!=null)
                //{
                //    var newRemarkData = new
                //    {
                //        imei,
                //        time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
                //        commandValue = new
                //        {
                //            systolicCalibrationValue = systolicRefValue,  //收缩压标定值,值为0 表示不生效
                //            diastolicCalibrationValue = diastolicRefValue, //舒张压标定值,值为0表示不生效
                //            systolicIncValue, //收缩压显示增量,值为0 表示不生效
                //            diastolicIncValue  //舒张压显示增量,值为0 表示不生效
                //        }
                //    };
                //    var newRemarkStr = $"{remarks}:{JsonConvert.SerializeObject(newRemarkData)}|";

                //    personCache["person"]!["remarks"] = newRemarkStr;
                //    bool cacheFlag = await _personCacheMgr.UpdateDeviceGpsPersonCacheObjectBySerialNoAsync(personCache, imei);
                //    if (cacheFlag)
                //    {
                //        GeneralParam condition = new()
                //        {
                //            Filters = new List<QueryFilterCondition> {
                //            new QueryFilterCondition {
                //                Key=nameof(GpsDevice.Serialno),
                //                Value=imei,
                //                Operator= QueryOperatorEnum.Equal,
                //                ValueType=QueryValueTypeEnum.String
                //            }
                //        },
                //            OrderBys = new List<OrderByCondition> { new OrderByCondition { Key = "serialno", IsDesc = true } }

                //        };
                //        _logger.LogInformation($"{imei} 更新缓存{nameof(UpdatePersonRemarksAsync)}成功,{JsonConvert.SerializeObject(personCache)}");
                //        // 读取数据库
                //        var person = await _gpsPersonApiClient.GetFirstAsync(condition, new RequestHeader() { RequestId = $"{imei}" }).ConfigureAwait(false);
                //        // 更新字段
                //        person!.Remarks = newRemarkStr;
                //        await _gpsPersonApiClient.UpdateAsync(person, new RequestHeader() { RequestId = $"{imei}" }).ConfigureAwait(false);
                //        _logger.LogInformation($"{imei} 更新Person remarks字段|{person.Remarks}");

                //    }
                //    else
                //    {
                //        _logger.LogInformation($"{imei} 更新缓存和数据库{nameof(UpdatePersonRemarksAsync)}失败,{JsonConvert.SerializeObject(personCache)}");
                //    }
                //    flag = cacheFlag;
                //}
            }
            catch (Exception ex)
            {
                _logger.LogError($"{nameof(UpdatePersonRemarksAsync)} {imei}--更新个人信息异常:{ex.Message}, {ex.StackTrace}");
            }
            return flag;
        }

        #endregion


        #region 平台下发胎心监测参数
       


        /// <summary>
        /// 胎心设置
        /// </summary>
        /// <param name="serialno"></param>
        /// <param name="modeStatus"></param>
        /// <param name="maxValue"></param>
        /// <param name="minValue"></param>
        /// <returns></returns>
        public async Task<bool> SetFetalConfig(string serialno, int modeStatus=0, int maxValue=0, int minValue = 0)
        {
            try
            {
                #region 读取缓存
                // db7.HashGet("TELPO#GPSDEVICE_WATCH_CONFIG_HASH","861281060086083_0067")
                var watchConfig = await _deviceCacheMgr.GetGpsDeviceWatchConfigCacheObjectBySerialNoAsync(serialno, "0067");
                if (watchConfig == null)
                {
                    return false;
                }
                #endregion

                #region 获取B端 Token
                string tokenAuthData = await getAccessToken2(serialno).ConfigureAwait(false);
                if (tokenAuthData == null)
                {
                    return false;
                }
                #endregion
                _logger.LogInformation($" SetFetalConfig Token TelpoManufactorId: {tokenAuthData}");
                #region 发送到B端
                List<KeyValuePair<string, string>> headers = new()
                {
                    new KeyValuePair<string, string>("AccessToken", tokenAuthData)
                };


                //var data = new
                //{
                //    imeis = new string[] { serialno },
                //    enabled = (int)watchConfig["enabled"]!,
                //    interval= (int)watchConfig["interval"]!,
                //    triggerHighFreqHigh = maxValue == 0 ? (int)watchConfig["triggerHighFreqHigh"]! : maxValue,
                //    triggerHighFreqLow = minValue == 0 ? (int)watchConfig["triggerHighFreqLow"]! : minValue,
                //    highFreqSampleTimes = (int)watchConfig["highFreqSampleTimes"]!,
                //    highFreqSampleInterval = (int)watchConfig["highFreqSampleInterval"]!,
                //    stopHighFreqSampleCount = (int)watchConfig["stopHighFreqSampleCount"]!,
                //    mode = modeStatus,
                //    edoc = watchConfig["EDOC"]!,
                //    vibrateEnabled = (int)watchConfig["vibrateEnabled"]!,
                //    lcdEnabled = (int)watchConfig["lcdEnabled"]!,
                //    upperAlarmThreshold = (int)watchConfig["upperAlarmThreshold"]!,
                //    lowerAlarmThreshold = (int)watchConfig["lowerAlarmThreshold"]!
                //};
                watchConfig["mode"] = modeStatus;
                watchConfig["triggerHighFreqHigh"] = maxValue == 0 ? (int)watchConfig["triggerHighFreqHigh"]! : maxValue;
                watchConfig["triggerHighFreqLow"] = minValue == 0 ? (int)watchConfig["triggerHighFreqLow"]! : minValue;

                var data = watchConfig;

                var setUrl = $"{_configService.IotCore}/SetFetalConfig";
                _logger.LogInformation($"{setUrl} 请求 {JsonConvert.SerializeObject(JsonConvert.SerializeObject(data))}");
                var res = await _httpHelper.HttpToPostAsync(setUrl, data, headers).ConfigureAwait(false);
                _logger.LogInformation($"{setUrl} 响应 {res}");
                var resJToken = JsonConvert.DeserializeObject(res ?? string.Empty) as JToken;
                return resJToken?["message"]?.ToString().Equals("ok") ?? false;
                //response.Flag = resJToken?["message"]?.ToString().Equals("ok") ?? false;
                //response.Flag = Convert.ToBoolean(resJToken?["succeed"]?.ToString());
                //if (!response.Flag)
                //{
                //    response.Message = resJToken?["message"]?.ToString()!;
                //}
                #endregion
            }
            catch (Exception ex)
            {
                _logger.LogError($"{nameof(SetFetalConfig)} 下发胎心检测参数异常:{ex.Message}, {ex.StackTrace}");
                return false;
            }
        }
        /// <summary>
        /// 下发胎心数据
        /// </summary>
        /// <param name="serialno"></param>
        /// <param name="fhr">心率值</param>
        /// <param name="sampleTime">检测时间(时间戳)</param>
        /// <param name="isAbnormal">0 //是否异常 0 表示正常;1表示偏高;2表示偏低</param>
        /// <returns></returns>
        public async Task<bool> SetFetalHeartRateConfig(string serialno, int fhr, string sampleTime, int isAbnormal)
        {

            try
            {
                #region 读取缓存
                // db7.HashGet("TELPO#GPSDEVICE_WATCH_CONFIG_HASH","861281060086083_0067")
                var watchConfig = await _deviceCacheMgr.GetGpsDeviceWatchConfigCacheObjectBySerialNoAsync(serialno, "0067");
                if (watchConfig == null)
                {
                    return false;
                }

                #endregion

                #region 获取B端 Token
                string tokenAuthData = await getAccessToken2(serialno).ConfigureAwait(false);
                if (tokenAuthData == null)
                {
                    return false;
                }
                #endregion

                #region 下发数据
                List<KeyValuePair<string, string>> headers = new()
                {
                    new KeyValuePair<string, string>("AccessToken", tokenAuthData)
                };
                _logger.LogInformation($" SetFetalHeartRateConfig Token TelpoManufactorId: {tokenAuthData}");
                var data = new
                {
                    imei = serialno,
                    heartValue = fhr,
                    sampleTime = sampleTime.Length > 10 ? sampleTime.Substring(0, 10) : sampleTime,
                    isAbnormal
                };

                var setUrl = $"{_configService.IotCore}/SetFetalHeartRateConfig";
                _logger.LogInformation($"{setUrl} 请求 {JsonConvert.SerializeObject(JsonConvert.SerializeObject(data))}");
                var res = await _httpHelper.HttpToPostAsync(setUrl, data, headers).ConfigureAwait(false);
                _logger.LogInformation($"{setUrl} 响应 {res}");
                var resJToken = JsonConvert.DeserializeObject(res ?? string.Empty) as JToken;
                return resJToken?["message"]?.ToString().Equals("ok") ?? false;

                #endregion

            }
            catch (Exception ex)
            {
                _logger.LogError($"{nameof(SetFetalHeartRateConfig)} 下发胎心数据异常:{ex.Message}, {ex.StackTrace}");
                return false;
            }

        }
     
        public async Task<bool> SetFetalMovementConfig(string serialno,int fm, string sampleTime, int isAbnormal)
        {
            try
            {
                #region 读取缓存
                // db7.HashGet("TELPO#GPSDEVICE_WATCH_CONFIG_HASH","861281060086083_0067")
                var watchConfig = await _deviceCacheMgr.GetGpsDeviceWatchConfigCacheObjectBySerialNoAsync(serialno, "0067");
                if (watchConfig == null)
                {
                    return false;
                }

                #endregion

                #region 获取B端 Token
                string tokenAuthData = await getAccessToken2(serialno).ConfigureAwait(false);
                if (tokenAuthData == null)
                {
                    return false;
                }
                #endregion

                #region 下发数据
                List<KeyValuePair<string, string>> headers = new()
                {
                    new KeyValuePair<string, string>("AccessToken", tokenAuthData)
                };
                _logger.LogInformation($" SetFetalHeartRateConfig Token TelpoManufactorId: {tokenAuthData}");
                var data = new
                {
                    imei = serialno,
                    movementValue = fm,
                    sampleTime = sampleTime.Length > 10 ? sampleTime.Substring(0, 10) : sampleTime,
                    isAbnormal
                };

                var setUrl = $"{_configService.IotCore}/SetFetalMovementConfig";
                _logger.LogInformation($"{setUrl} 请求 {JsonConvert.SerializeObject(JsonConvert.SerializeObject(data))}");
                var res = await _httpHelper.HttpToPostAsync(setUrl, data, headers).ConfigureAwait(false);
                _logger.LogInformation($"{setUrl} 响应 {res}");
                var resJToken = JsonConvert.DeserializeObject(res ?? string.Empty) as JToken;
                return resJToken?["message"]?.ToString().Equals("ok") ?? false;

                #endregion
            }
            catch (Exception ex)
            {
                _logger.LogError($"{nameof(SetFetalMovementConfig)} 下发胎动数据异常:{ex.Message}, {ex.StackTrace}");
                return false;
            }

        }


        private async Task<string> getAccessToken2(string serialno)
        {
            var getTokenUrl = $"{_configService.IotAuth}/getAccessToken2";
            var tokenReq = new
            {
                manufactorId = "7c7c38cb-d045-41d8-b3d0-fcaaa84a8f02",
                imei = serialno
            };
            _logger.LogInformation($"{getTokenUrl} 请求 {JsonConvert.SerializeObject(tokenReq)}");
            var resToken = await _httpHelper.HttpToPostAsync(getTokenUrl, tokenReq).ConfigureAwait(false);
            _logger.LogInformation($"{getTokenUrl} 响应 {resToken}");
            var tokenAuth = JsonConvert.DeserializeObject(resToken ?? string.Empty) as JToken;
            var tokenAuthData = tokenAuth?["data"]?.ToString() ?? string.Empty;
            return tokenAuthData;
        }

        #endregion

    }
}