using Lada.Framework.Data.Domains;
using Lada.Framework.Data.Repositories;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Memory;

namespace Lada.Framework.Infrastructures.Services
{
    /// <summary>
    /// Interface cho service quản lý cấu hình ứng dụng
    /// </summary>
    public interface IAppConfigService
    {
        /// <summary>
        /// Lấy giá trị cấu hình theo key
        /// </summary>
        /// <param name="key">Key cấu hình</param>
        /// <returns>Giá trị cấu hình</returns>
        Task<string> GetConfigValueAsync(string key);

        /// <summary>
        /// Lấy giá trị cấu hình theo key với giá trị mặc định
        /// </summary>
        /// <param name="key">Key cấu hình</param>
        /// <param name="defaultValue">Giá trị mặc định nếu không tìm thấy</param>
        /// <returns>Giá trị cấu hình hoặc giá trị mặc định</returns>
        Task<string> GetConfigValueAsync(string key, string defaultValue);

        /// <summary>
        /// Load tất cả configs vào cache
        /// </summary>
        /// <returns></returns>
        Task LoadConfigsToCacheAsync();

        /// <summary>
        /// Cập nhật giá trị cấu hình
        /// </summary>
        /// <param name="key">Key cấu hình</param>
        /// <param name="value">Giá trị mới</param>
        /// <returns>True nếu cập nhật thành công</returns>
        Task<bool> SetConfigValueAsync(string key, string value);
    }

    /// <summary>
    /// Implementation của AppConfigService trong Framework
    /// </summary>
    public class AppConfigService : IAppConfigService
    {
        private readonly IRepository<AppConfig> _appConfigRepository;
        private readonly IMemoryCache _memoryCache;
        private readonly string _cacheKeyPrefix = "AppConfig_";

        public AppConfigService(IRepository<AppConfig> appConfigRepository, IMemoryCache memoryCache)
        {
            _appConfigRepository = appConfigRepository;
            _memoryCache = memoryCache;
        }

        public async Task<string> GetConfigValueAsync(string key)
        {
            if (!_memoryCache.TryGetValue($"{_cacheKeyPrefix}{key}", out string? value))
            {
                var config = await _appConfigRepository.Query().FirstOrDefaultAsync(c => c.Key == key);
                if (config != null)
                {
                    value = config.Value;
                    _memoryCache.Set($"{_cacheKeyPrefix}{key}", value, TimeSpan.FromHours(1));
                }
            }
            return value ?? string.Empty;
        }

        public async Task<string> GetConfigValueAsync(string key, string defaultValue)
        {
            var value = await GetConfigValueAsync(key);
            return string.IsNullOrEmpty(value) ? defaultValue : value;
        }

        public async Task LoadConfigsToCacheAsync()
        {
            var configs = await _appConfigRepository.Query().ToListAsync();
            foreach (var config in configs)
            {
                _memoryCache.Set($"{_cacheKeyPrefix}{config.Key}", config.Value, TimeSpan.FromHours(1));
            }
        }

        public async Task<bool> SetConfigValueAsync(string key, string value)
        {
            try
            {
                var config = await _appConfigRepository.Query().FirstOrDefaultAsync(c => c.Key == key);
                if (config != null)
                {
                    config.Value = value;
                    await _appConfigRepository.UpdateAsync(config);
                }
                else
                {
                    config = new AppConfig { Key = key, Value = value };
                    await _appConfigRepository.InsertAsync(config);
                }

                // Update cache
                _memoryCache.Set($"{_cacheKeyPrefix}{key}", value, TimeSpan.FromHours(1));
                return true;
            }
            catch
            {
                return false;
            }
        }
    }
}
