using bitforum.Models;
using bitforum.Repository;
using bitforum.Helpers;

namespace bitforum.Services
{
    public interface ISetupService
    {
        // 프로그램 시작 시 Config 값을 메모리에 저장
        public Task LoadSetupAsync();

        // Config 값을 조회
        public string? GetConfig(string key);

        // Config 값을 최신으로 갱신
        public Task RefreshConfigAsync();
    }

    public static class Config
    {
        public static BasicForm Basic = new BasicForm();
        public static MetaForm Meta = new MetaForm();
        public static CompanyForm Company = new CompanyForm();
        public static RegisterForm Register = new RegisterForm();
        public static EmailTemplate EmailTemplate = new EmailTemplate();
        public static Dictionary<string, string> Map = new();
    }

    public class SetupService : ISetupService
    {
        private readonly IConfigRepository _configRepository; // Scoped 서비스 생성을 위한 Factory
        private readonly IRedisRepository _redisRepository;

        private const string _RedisConfigKey = "Config:All";
        private const int _RedisCacheExpiration = 60;
        private Dictionary<string, string> _config = new();

        public SetupService(IConfigRepository configRepository, IRedisRepository redisRepository)
        {
            _configRepository = configRepository;
            _redisRepository = redisRepository;

            Task.Run(LoadSetupAsync).Wait();
        }

        public async Task LoadSetupAsync()
        {
            // 먼전 Redis에 저장된 Config 값을 조회
            var config = await _redisRepository.GetObjectAsync<Dictionary<string, string>>(_RedisConfigKey);
            if (config is null)
            {
                // 없으면 DB에서 조회
                config = _configRepository.GetAll();
                await _redisRepository.SetObjectAsync(_RedisConfigKey, config, _RedisCacheExpiration);
            }

            lock (_config)
            {
                _config.Clear();
                foreach (var (k, v) in config)
                {
                    _config[k] = v;
                }

                Config.Basic = Functions.Mapping<BasicForm>(_config);
                Config.Meta = Functions.Mapping<MetaForm>(_config);
                Config.Company = Functions.Mapping<CompanyForm>(_config);
                Config.Register = Functions.Mapping<RegisterForm>(_config);
                Config.EmailTemplate = Functions.Mapping<EmailTemplate>(_config);
                Config.Map = _config;
            }
        }

        public string? GetConfig(string key)
        {
            lock (_config)
            {
                return _config.TryGetValue(key, out var value) ? value : null;
            }
        }

        public async Task RefreshConfigAsync()
        {
            await _redisRepository.DeleteAsync(_RedisConfigKey);
            await LoadSetupAsync();
        }
    }
}
