using HuanMeng.DotNetCore.CacheHelper.Contract;
using HuanMeng.DotNetCore.Redis;

using Microsoft.EntityFrameworkCore.Metadata.Internal;

using Newtonsoft.Json;

using StackExchange.Redis;

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace HuanMeng.DotNetCore.CacheHelper;

/// <summary>
/// 缓存扩展-
/// </summary>
public abstract class CommonDataEntityCache<T> : ICacheClearData, ICacheReloadData where T : class
{
    /// <summary>
    /// 
    /// </summary>
    protected object lockObj;
    /// <summary>
    /// 过期时间
    /// </summary>
    protected int cacheTime;

    protected CommonDataEntityCache(object lockObj, int cacheTime = 36000)
    {
        this.lockObj = lockObj;
        this.cacheTime = cacheTime;
    }


    /// <summary>
    /// 
    /// </summary>
    public abstract string key { get; }

    /// <summary>
    /// 缓存数据
    /// </summary>
    protected List<T>? _dataList;

    /// <summary>
    /// 数据
    /// </summary>
    public virtual List<T> DataList
    {
        get
        {
            if (_dataList == null)
            {
                var tempDataList = MemoryCacheHelper.GetCache<List<T>>(key);
                if (tempDataList == null)
                {
                    lock (lockObj)
                    {
                        tempDataList = MemoryCacheHelper.GetCache<List<T>>(key);
                        if (tempDataList == null)
                        {
                            tempDataList = GetDataList();
                            MemoryCacheHelper.SetCache(key, tempDataList, cacheTime);
                        }
                    }
                }
                _dataList = JsonConvert.DeserializeObject<List<T>>(JsonConvert.SerializeObject(tempDataList));
            }
            return _dataList ?? new List<T>();
        }
    }


    /// <summary>
    /// 获取缓存数据
    /// </summary>
    public abstract List<T> GetDataList();

    public virtual bool ClearData()
    {
        lock (lockObj)
        {
            MemoryCacheHelper.DelCache(key);
            _dataList = null;
        }
        return true;
    }

    public virtual void ReloadData()
    {
        lock (lockObj)
        {
            var tempDataList = GetDataList();
            MemoryCacheHelper.SetCache(key, tempDataList, cacheTime);
            _dataList = tempDataList;
        }
    }
}


/// <summary>
/// 缓存扩展-
/// </summary>
public abstract class RedisDataEntityCache<T> : CommonDataEntityCache<T>, ICacheClearLocalData where T : class
{
    public IDatabase database;
    /// <summary>
    /// 
    /// </summary>
    protected object lockObj;
    /// <summary>
    /// 过期时间
    /// </summary>
    protected int cacheTime;

    private string name;

    protected RedisDataEntityCache(IDatabase database, int cacheTime = 36000, string name = "") : base(new object(), cacheTime)
    {
        this.lockObj = lockObj;
        this.cacheTime = cacheTime;
        this.database = database;
        this.name = name;
    }

    public int index = 0;
    /// <summary>
    /// 缓存数据
    /// </summary>
    protected List<T>? _dataList;

    /// <summary>
    /// 数据
    /// </summary>
    public override List<T> DataList
    {
        get
        {

            if (_dataList == null)
            {
            start:
                var tempDataList = database.StringGet<List<T>>(key);
                if (tempDataList == null)
                {
                    if (database.StringSetLock($"lock:{key}", "", 5))
                    {

                        if (tempDataList == null)
                        {

                            tempDataList = GetDataList();
                            if (cacheTime == 0)
                            {
                                database.StringSet(key, tempDataList);
                            }
                            else
                            {
                                database.StringSet(key, tempDataList, TimeSpan.FromSeconds(cacheTime));
                            }
                        }
                        //_dataList = JsonConvert.DeserializeObject<List<T>>(JsonConvert.SerializeObject(tempDataList));
                        database.KeyDeleteAsync($"lock:{key}").Wait();
                    }
                    else
                    {
                        index++;
                        Thread.Sleep(500);
                        tempDataList = database.StringGet<List<T>>(key);
                        if (tempDataList == null)
                        {
                            if (index < 10)
                            {
                                goto start;
                            }
                        }
                    }
                }
                _dataList = tempDataList;
            }
            return _dataList ?? new List<T>();
        }
    }




    public virtual bool ClearData()
    {
        if (database.StringSetLock($"lock:{key}", "", 5))
        {
            database.KeyDelete(key);
            _dataList = null;
            database.KeyDeleteAsync($"lock:{key}").Wait();
        }
        return true;
    }

    public virtual void ReloadData()
    {
        if (database.StringSetLock($"lock:{key}", "", 5))
        {
            var tempDataList = GetDataList();
            if (cacheTime == 0)
            {
                database.StringSet(key, tempDataList);
            }
            else
            {
                database.StringSet(key, tempDataList, TimeSpan.FromSeconds(cacheTime));
            }
            _dataList = tempDataList;
            database.KeyDeleteAsync($"lock:{key}").Wait();
            database.StringSet($"time:{key.Replace(":", ".")}", $"刷新{name}缓存时间{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}");

        }
    }

    public bool ClearLocalData()
    {
        _dataList = null;
        return true;
    }
}
