using Atomx.Common.Constant;
using Atomx.Common.Entities;
using Atomx.Common.Enums;
using Atomx.Common.Models;
using Atomx.Utils.Extension;
using Mapster;

namespace Atomx.Data.CacheServices
{
    public partial interface ICacheService
    {
        /// <summary>
        /// 获取内容分类列表
        /// </summary>
        /// <param name="reload"></param>
        /// <returns></returns>
        Task<List<CategoryItemModel>> GetContentCategoryList(bool? reload = false);

        /// <summary>
        /// 获取产品分类列表
        /// </summary>
        /// <param name="reload"></param>
        /// <returns></returns>
        Task<List<CategoryItemModel>> GetProductCategoryList(bool? reload = false);

        /// <summary>
        /// 获取可用的缓存信息
        /// </summary>
        /// <returns></returns>
        Task<List<Category>> GetContentCategories(List<Category>? data = null);


        /// <summary>
        /// 通过ID获取或更新缓存
        /// </summary>
        /// <param name="id"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        Task<Category> GetContentCategoryById(long id, Category? data = null);

        /// <summary>
        /// 从缓存中移除分类缓存
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        Task RemoveContentCategory(long id);

        /// <summary>
        /// 获取可用的缓存信息
        /// </summary>
        /// <param name="reload"></param>
        /// <returns></returns>
        Task<List<Category>> GetProductCategories(bool? reload = false);

        /// <summary>
        /// 通过ID获取或更新缓存
        /// </summary>
        /// <param name="id"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        Task<Category> GetProductCategoryById(long id, Category? data = null);

        /// <summary>
        /// 重缓存中移除产品分类
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        Task RemoveProductCategory(long id);
    }
    public partial class CacheService : ICacheService
    {
        /// <summary>
        /// 获取内容分类列表
        /// </summary>
        /// <param name="reload"></param>
        /// <returns></returns>
        public async Task<List<CategoryItemModel>> GetContentCategoryList(bool? reload = false)
        {
            var cacheData = await GetCacheAsync<List<CategoryItemModel>>(CacheKeys.ContentCategories);
            bool needReload = reload.HasValue ? reload.Value : false;
            if (cacheData == null || needReload)
            {
                var category = _dbContext.Categories.Where(p => p.Type == (int)CategoryType.Content).ToList();
                var list = new List<CategoryItemModel>();
                cacheData = BuildCategoryList(list, category, 0);
                await SetCacheAsync(CacheKeys.ContentCategories, cacheData);
            }
            return cacheData;
        }

        /// <summary>
        /// 获取产品分类列表
        /// </summary>
        /// <param name="reload"></param>
        /// <returns></returns>
        public async Task<List<CategoryItemModel>> GetProductCategoryList(bool? reload = false)
        {
            var cacheData = await GetCacheAsync<List<CategoryItemModel>>(CacheKeys.ProductCategories);
            bool needReload = reload.HasValue ? reload.Value : false;
            if (cacheData == null || needReload)
            {
                var category = _dbContext.Categories.Where(p => p.Type == (int)CategoryType.Product).ToList();
                var list = new List<CategoryItemModel>();
                cacheData = BuildCategoryList(list, category, 0);
                await SetCacheAsync(CacheKeys.ProductCategories, cacheData);
            }
            return cacheData;
        }

        List<CategoryItemModel> BuildCategoryList(List<CategoryItemModel> list, List<Category> data, long parentId)
        {
            var categories = data.Where(p => p.ParentId == parentId).OrderBy(p => p.DisplayOrder).ToList();
            foreach (var item in categories)
            {
                var category = item.Adapt<CategoryItemModel>();

                if (!string.IsNullOrEmpty(item.Path))
                {
                    var ids = item.Path.Split(',').Select(p => p.ToLong()).ToList();
                    var breadcrumbs = string.Empty;
                    foreach (var id in ids)
                    {
                        var name = data.Where(p => p.Id == id).Select(p => p.Name).SingleOrDefault();
                        if (!string.IsNullOrEmpty(breadcrumbs))
                        {
                            breadcrumbs = breadcrumbs + " >> " + name;
                        }
                        else
                        {
                            breadcrumbs = name;
                        }
                    }

                    category.Breadcrumbs = breadcrumbs;
                    category.Breadcrumbs = breadcrumbs + " >> " + category.Name;
                }
                else
                {
                    category.Breadcrumbs = item.Name;
                }
                list.Add(category);
                if (data.Count(p => p.ParentId == item.Id) > 0)
                {
                    List<CategoryItemModel> childlist = new List<CategoryItemModel>();
                    childlist = BuildCategoryList(childlist, data, item.Id);
                    list.AddRange(childlist);
                }

            }
            return list;
        }

        public async Task<Category> GetProductCategoryById(long id, Category? data = null)
        {
            var cacheData = await GetProductCategories();
            if (data != null)
            {
                var category = cacheData.SingleOrDefault(p => p.Id == id);
                if (category != null)
                {
                    cacheData.Remove(category);
                    cacheData.Add(data);
                    await SetCacheAsync(CacheKeys.ProductCategories, cacheData);
                }
                else
                {
                    cacheData.Add(data);
                    await SetCacheAsync(CacheKeys.ProductCategories, cacheData);
                }
                return data;
            }
            else
            {
                var category = cacheData.SingleOrDefault(p => p.Id == id);
                if (category == null)
                {
                    category = _dbContext.Categories.SingleOrDefault(p => p.Id == id);
                    if (category != null)
                    {
                        cacheData.Add(category);
                        await SetCacheAsync(CacheKeys.ProductCategories, cacheData);
                    }
                }
                return category;
            }
        }

        public async Task RemoveProductCategory(long id)
        {
            var cacheData = await GetProductCategories();
            if (cacheData != null)
            {
                var data = cacheData.SingleOrDefault(p => p.Id == id);
                if (data != null)
                {
                    cacheData.Remove(data);
                    await SetCacheAsync(CacheKeys.ProductCategories, cacheData);
                }
            }
        }

        public async Task<List<Category>> GetContentCategories(List<Category>? data = null)
        {
            var cacheData = await GetCacheAsync<List<Category>>(CacheKeys.ContentCategories);
            if (data != null)
            {
                cacheData = data;
                await SetCacheAsync(CacheKeys.ContentCategories, cacheData);
            }
            else
            {
                if (cacheData == null)
                {
                    return new List<Category>();
                }
            }

            return cacheData;
        }


        /// <summary>
        /// 获取可用的缓存信息
        /// </summary>
        /// <param name="reload"></param>
        /// <returns></returns>
        public async Task<List<Category>> GetProductCategories(bool? reload = false)
        {
            var cacheData = await GetCacheAsync<List<Category>>(CacheKeys.ProductCategories);
            bool needReload = reload.HasValue ? reload.Value : false;
            if (cacheData == null || needReload)
            {
                var data = _dbContext.Categories.Where(p => p.Type == (int)CategoryType.Product && p.Enabled).ToList();

                cacheData = data;

                await SetCacheAsync(CacheKeys.ProductCategories, cacheData);
            }
            else
            {
                if (cacheData == null)
                {
                    return new List<Category>();
                }
            }

            return cacheData;
        }

        public async Task<Category> GetContentCategoryById(long id, Category? data = null)
        {
            var cacheData = await GetContentCategories();
            if (data != null)
            {
                var category = cacheData.SingleOrDefault(p => p.Id == id);
                if (category != null)
                {
                    cacheData.Remove(category);
                    cacheData.Add(data);
                    await SetCacheAsync(CacheKeys.ContentCategories, cacheData);
                }
                else
                {
                    cacheData.Add(data);
                    await SetCacheAsync(CacheKeys.ContentCategories, cacheData);
                }
                return data;
            }
            else
            {
                var category = cacheData.SingleOrDefault(p => p.Id == id);
                if (category == null)
                {
                    category = _dbContext.Categories.SingleOrDefault(p => p.Id == id);
                    if (category != null)
                    {
                        cacheData.Add(category);
                        await SetCacheAsync(CacheKeys.ContentCategories, cacheData);
                    }
                }
                return category;

            }
        }

        public async Task RemoveContentCategory(long id)
        {
            var cacheData = await GetContentCategories();
            if (cacheData != null)
            {
                var data = cacheData.SingleOrDefault(p => p.Id == id);
                if (data != null)
                {
                    cacheData.Remove(data);
                    await SetCacheAsync(CacheKeys.ContentCategories, cacheData);
                }
            }
        }
    }
}
