using HealthMonitor.Core.Dal;
using HealthMonitor.Util.Entities.HealthMonitor;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System.Security.Cryptography;
using System.Text;

namespace HealthMonitor.Service.Cache
{
    public class BloodPressReferenceValueCacheManager
    {
        private readonly ILogger<BloodPressReferenceValueCacheManager> _logger;
        protected readonly IHealthMonitorDataAccessor _dataAccessor;

        private static object _syncLocker = new object();
        private MD5 _md5;
        private const string CACHE_KEY_BP_REF_VALUE = "HM_REF_Val_";

        public BloodPressReferenceValueCacheManager(
             IHealthMonitorDataAccessor dataAccessor,
             ILogger<BloodPressReferenceValueCacheManager> logger
            ) 
        {
            _md5 = MD5.Create();
            _dataAccessor = dataAccessor;
            _logger = logger;
        }

        public async Task<HmBloodPressReferenceValue> GetBloodPressReferenceValueAsync(int age, int gender,bool isHypertension)
        {
            var hashModel = new
            {
                Index = $"{age}-{gender}-{isHypertension}"
            };
            var hash = ComputeHash(hashModel);
            var cacheKey = CACHE_KEY_BP_REF_VALUE + $"{hash}";

            var bpRef = await RedisHelper.GetAsync<HmBloodPressReferenceValue>(cacheKey).ConfigureAwait(false);
            if (bpRef == null)
            {
                bpRef = _dataAccessor
                  .GetFirstOrDefault<HmBloodPressReferenceValue>(
                  i =>
                  i.Age.Equals(age) &&
                  i.Gender.Equals(gender) &&
                  i.Hypertension.Equals(isHypertension)
                  );
                ;
                await RedisHelper.SetAsync(cacheKey, JsonConvert.SerializeObject(bpRef));
            }
            return bpRef;
        }


        private string ComputeHash(object data)
        {
            lock (_syncLocker)
            {
                var value = JsonConvert.SerializeObject(data);
                value = Convert.ToBase64String(_md5.ComputeHash(Encoding.UTF8.GetBytes(value)));
                return value;
            }
        }



    }
}