using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Haoliang.Models.System;
using Haoliang.Data.Repositories;

namespace Haoliang.Core.Services
{
    public interface ISystemConfigService
    {
        Task<SystemConfig> GetConfigAsync(string configKey);
        Task<SystemConfig> SetConfigAsync(string configKey, string configValue);
        Task<IEnumerable<SystemConfig>> GetAllConfigsAsync();
        Task<bool> DeleteConfigAsync(string configKey);
        Task<SystemConfig> GetOrCreateConfigAsync(string configKey, string defaultValue);
        Task<bool> ValidateConfigAsync(SystemConfig config);
    }

    public class SystemConfigService : ISystemConfigService
    {
        private readonly ISystemConfigRepository _configRepository;
        private readonly ILoggerService _logger;

        public SystemConfigService(
            ISystemConfigRepository configRepository,
            ILoggerService logger)
        {
            _configRepository = configRepository;
            _logger = logger;
        }

        public async Task<SystemConfig> GetConfigAsync(string configKey)
        {
            return await _configRepository.GetByKeyAsync(configKey);
        }

        public async Task<SystemConfig> SetConfigAsync(string configKey, string configValue)
        {
            var existingConfig = await _configRepository.GetByKeyAsync(configKey);
            
            if (existingConfig != null)
            {
                // Update existing config
                existingConfig.ConfigValue = configValue;
                existingConfig.UpdateTime = DateTime.Now;
                
                var updatedConfig = await _configRepository.UpdateAsync(existingConfig);
                await _logger.LogInformationAsync($"Updated config '{configKey}' with new value");
                return updatedConfig;
            }
            else
            {
                // Create new config
                var newConfig = new SystemConfig
                {
                    ConfigKey = configKey,
                    ConfigValue = configValue,
                    Description = $"Configuration for {configKey}",
                    CreatedAt = DateTime.Now,
                    UpdateTime = DateTime.Now
                };
                
                var createdConfig = await _configRepository.AddAsync(newConfig);
                await _logger.LogInformationAsync($"Created new config '{configKey}'");
                return createdConfig;
            }
        }

        public async Task<IEnumerable<SystemConfig>> GetAllConfigsAsync()
        {
            return await _configRepository.GetAllAsync();
        }

        public async Task<bool> DeleteConfigAsync(string configKey)
        {
            var config = await _configRepository.GetByKeyAsync(configKey);
            if (config != null)
            {
                var result = await _configRepository.DeleteAsync(config.ConfigId);
                if (result)
                {
                    await _logger.LogInformationAsync($"Deleted config '{configKey}'");
                }
                return result;
            }
            return false;
        }

        public async Task<SystemConfig> GetOrCreateConfigAsync(string configKey, string defaultValue)
        {
            var config = await GetConfigAsync(configKey);
            if (config == null)
            {
                return await SetConfigAsync(configKey, defaultValue);
            }
            return config;
        }

        public async Task<bool> ValidateConfigAsync(SystemConfig config)
        {
            if (config == null)
            {
                await _logger.LogWarningAsync("System config validation failed: config is null");
                return false;
            }

            if (string.IsNullOrEmpty(config.ConfigKey))
            {
                await _logger.LogWarningAsync("System config validation failed: config key is empty");
                return false;
            }

            if (string.IsNullOrEmpty(config.ConfigValue))
            {
                await _logger.LogWarningAsync($"System config validation failed: config value is empty for key '{config.ConfigKey}'");
                return false;
            }

            // Validate specific config keys
            if (config.ConfigKey == "DailyProductionTarget" && !int.TryParse(config.ConfigValue, out _))
            {
                await _logger.LogWarningAsync($"System config validation failed: invalid DailyProductionTarget value '{config.ConfigValue}'");
                return false;
            }

            if (config.ConfigKey == "CollectionInterval" && !int.TryParse(config.ConfigValue, out _))
            {
                await _logger.LogWarningAsync($"System config validation failed: invalid CollectionInterval value '{config.ConfigValue}'");
                return false;
            }

            return true;
        }
    }

    public class SystemConfigManager : ISystemConfigService
    {
        private readonly ISystemConfigRepository _configRepository;
        private readonly ILoggerService _logger;

        public SystemConfigManager(
            ISystemConfigRepository configRepository,
            ILoggerService logger)
        {
            _configRepository = configRepository;
            _logger = logger;
        }

        public async Task<SystemConfig> GetConfigAsync(string configKey)
        {
            return await _configRepository.GetByKeyAsync(configKey);
        }

        public async Task<SystemConfig> SetConfigAsync(string configKey, string configValue)
        {
            return await new SystemConfigService(_configRepository, _logger).SetConfigAsync(configKey, configValue);
        }

        public async Task<IEnumerable<SystemConfig>> GetAllConfigsAsync()
        {
            return await _configRepository.GetAllAsync();
        }

        public async Task<bool> DeleteConfigAsync(string configKey)
        {
            return await _configRepository.DeleteByKeyAsync(configKey);
        }

        public async Task<SystemConfig> GetOrCreateConfigAsync(string configKey, string defaultValue)
        {
            return await new SystemConfigService(_configRepository, _logger).GetOrCreateConfigAsync(configKey, defaultValue);
        }

        public async Task<bool> ValidateConfigAsync(SystemConfig config)
        {
            return await new SystemConfigService(_configRepository, _logger).ValidateConfigAsync(config);
        }
    }

    public class LoggingManager : ILoggingService
    {
        private readonly ILogRepository _logRepository;
        private readonly ILoggerService _logger;

        public LoggingManager(
            ILogRepository logRepository,
            ILoggerService logger)
        {
            _logRepository = logRepository;
            _logger = logger;
        }

        public async Task LogInformationAsync(string message)
        {
            await _logRepository.LogAsync(message, "Information");
            await _logger.LogInformationAsync(message);
        }

        public async Task LogWarningAsync(string message)
        {
            await _logRepository.LogAsync(message, "Warning");
            await _logger.LogWarningAsync(message);
        }

        public async Task LogErrorAsync(string message)
        {
            await _logRepository.LogAsync(message, "Error");
            await _logger.LogErrorAsync(message);
        }

        public async Task LogDebugAsync(string message)
        {
            await _logRepository.LogAsync(message, "Debug");
            await _logger.LogDebugAsync(message);
        }

        public async Task LogExceptionAsync(Exception ex, string message)
        {
            var fullMessage = $"{message}: {ex.Message}\n{ex.StackTrace}";
            await _logRepository.LogAsync(fullMessage, "Error");
            await _logger.LogErrorAsync(fullMessage);
        }

        public async Task LogAsync(LogLevel level, string message)
        {
            await _logRepository.LogAsync(message, level.ToString());
            await LogByLevel(level, message);
        }

        private async Task LogByLevel(LogLevel level, string message)
        {
            switch (level)
            {
                case LogLevel.Trace:
                    await _logger.LogDebugAsync(message);
                    break;
                case LogLevel.Debug:
                    await _logger.LogDebugAsync(message);
                    break;
                case LogLevel.Information:
                    await _logger.LogInformationAsync(message);
                    break;
                case LogLevel.Warning:
                    await _logger.LogWarningAsync(message);
                    break;
                case LogLevel.Error:
                case LogLevel.Critical:
                    await _logger.LogErrorAsync(message);
                    break;
                default:
                    await _logger.LogInformationAsync(message);
                    break;
            }
        }
    }
}