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

namespace ladaexpress.vn.Infrastructures.Services
{
    /// <summary>
    /// Implementation của AppConfigService cho ladaexpress.vn
    /// </summary>
    public class AppConfigService : IAppConfigService
    {
        private readonly IRepository<AppConfig> _appConfigRepository;
        private readonly IMemoryCache _memoryCache;
        private readonly string _cacheKeyPrefix = "WebAppConfig_";
        private readonly ILogger<AppConfigService> _logger;

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

        public async Task<string> GetConfigValueAsync(string key)
        {
            try
            {
                var cacheKey = $"{_cacheKeyPrefix}{key}";

                if (!_memoryCache.TryGetValue(cacheKey, out string? value))
                {
                    var config = await _appConfigRepository.Query()
                        .FirstOrDefaultAsync(c => c.Key == key);

                    if (config != null)
                    {
                        value = config.Value;
                        // Cache for 1 hour
                        _memoryCache.Set(cacheKey, value, TimeSpan.FromHours(1));
                        _logger.LogDebug("Loaded config '{Key}' from database and cached", key);
                    }
                    else
                    {
                        _logger.LogWarning("Config key '{Key}' not found in database", key);
                    }
                }

                return value ?? string.Empty;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting config value for key '{Key}'", key);
                return 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()
        {
            try
            {
                var configs = await _appConfigRepository.Query().ToListAsync();
                var cacheOptions = new MemoryCacheEntryOptions
                {
                    AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(1),
                    SlidingExpiration = TimeSpan.FromMinutes(30)
                };

                foreach (var config in configs)
                {
                    var cacheKey = $"{_cacheKeyPrefix}{config.Key}";
                    _memoryCache.Set(cacheKey, config.Value, cacheOptions);
                }

                _logger.LogInformation("Loaded {Count} configs into cache", configs.Count);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error loading configs to cache");
            }
        }

        public async Task ReloadConfigCacheAsync()
        {
            try
            {
                // Clear existing cache
                var configs = await _appConfigRepository.Query().ToListAsync();
                foreach (var config in configs)
                {
                    var cacheKey = $"{_cacheKeyPrefix}{config.Key}";
                    _memoryCache.Remove(cacheKey);
                }

                // Reload cache
                await LoadConfigsToCacheAsync();
                _logger.LogInformation("Config cache reloaded successfully");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error reloading config cache");
            }
        }

        public void InvalidateCache(string key)
        {
            try
            {
                var cacheKey = $"{_cacheKeyPrefix}{key}";
                _memoryCache.Remove(cacheKey);
                _logger.LogDebug("Invalidated cache for key '{Key}'", key);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error invalidating cache for key '{Key}'", key);
            }
        }

        public async Task<List<AppConfig>> GetAllConfigsAsync()
        {
            try
            {
                return await _appConfigRepository.Query().OrderBy(c => c.Key).ToListAsync();
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting all configs");
                return new List<AppConfig>();
            }
        }
    }
}