using Atomx.Common.Models;
using Microsoft.JSInterop;
using System.Text.Json;

namespace Atomx.Admin.Client.Services
{
    public interface ILocalizationService
    {
        /// <summary>
        /// 根据name获取制定文化语言的译文
        /// </summary>
        /// <param name="name"></param>
        /// <param name="culture"></param>
        /// <returns></returns>
        Task<string?> GetStringAsync(string name, string? culture = null);

        /// <summary>
        /// 把本地化文化语言加载到内存中
        /// </summary>
        /// <param name="culture"></param>
        /// <returns></returns>
        Task<bool> LoadResourcesAsync(string culture);


        event EventHandler<string>? ResourcesUpdated;
    }

    public class LocalizationClientService : ILocalizationService, IAsyncDisposable
    {
        private readonly HttpService _httpService;
        private readonly HttpClient _httpClient;
        private readonly IJSRuntime _jsRuntime;
        private readonly ILogger<LocalizationClientService> _logger;

        private readonly Dictionary<string, Dictionary<string, string>> _resources = new();
        private readonly Dictionary<string, string> _versions = new();
        private readonly SemaphoreSlim _semaphore = new(1, 1);

        public event EventHandler<string>? ResourcesUpdated;

        public LocalizationClientService(
            HttpService httpService,
            HttpClient httpClient,
            IJSRuntime jsRuntime,
            ILogger<LocalizationClientService> logger)
        {
            _httpService = httpService;
            _httpClient = httpClient;
            _jsRuntime = jsRuntime;
            _logger = logger;
        }

        /// <summary>
        /// 根据name获取制定文化语言的译文
        /// </summary>
        /// <param name="name"></param>
        /// <param name="culture"></param>
        /// <returns></returns>
        public async Task<string?> GetStringAsync(string name, string? culture = null)
        {
            culture ??= await GetCurrentCultureAsync();

            if (_resources.TryGetValue(culture, out var cultureResources))
            {
                if (cultureResources.TryGetValue(name, out var value))
                {
                    return value;
                }

                // 键不存在，触发资源更新检查
                _ = Task.Run(async () => await CheckAndUpdateResourcesAsync(culture));
            }
            else
            {
                // 资源未加载，立即加载
                await LoadResourcesAsync(culture);

                // 重试获取
                if (_resources.TryGetValue(culture, out cultureResources) &&
                    cultureResources.TryGetValue(name, out var value))
                {
                    return value;
                }
            }

            _logger.LogWarning("Localization key not found: {Key} for culture: {Culture}", name, culture);
            return null;
        }

        /// <summary>
        /// 把本地化文化语言加载到内存中
        /// </summary>
        /// <param name="culture"></param>
        /// <returns></returns>
        public async Task<bool> LoadResourcesAsync(string culture)
        {
            await _semaphore.WaitAsync();
            try
            {
                // 先尝试从localStorage加载
                if (await TryLoadFromLocalStorage(culture))
                {
                    // 检查服务器版本，如果需要更新则从服务器加载
                    if (await CheckAndUpdateFromServer(culture))
                    {
                        return true;
                    }
                    return true; // 本地版本仍然有效
                }

                // 从服务器加载
                return await LoadFromServer(culture);
            }
            finally
            {
                _semaphore.Release();
            }
        }

        /// <summary>
        /// 从单例对象中获取版本记录
        /// </summary>
        /// <param name="culture"></param>
        /// <returns></returns>
        private async Task<string?> GetResourceVersionAsync(string culture)
        {
            if (_versions.TryGetValue(culture, out var version))
            {
                return version;
            }

            var storedVersion = await GetStoredVersion(culture);
            return storedVersion;
        }

        /// <summary>
        /// 检查更新资源
        /// </summary>
        /// <param name="culture"></param>
        /// <returns></returns>
        private async Task<bool> CheckAndUpdateResourcesAsync(string culture)
        {
            return await CheckAndUpdateFromServer(culture);
        }

        /// <summary>
        /// 从本地加载文化语言数据
        /// </summary>
        /// <param name="culture"></param>
        /// <returns></returns>
        private async Task<bool> TryLoadFromLocalStorage(string culture)
        {
            try
            {
                var resourcesJson = await _jsRuntime.InvokeAsync<string?>("localStorage.getItem", $"locales_{culture}");
                var version = await _jsRuntime.InvokeAsync<string?>("localStorage.getItem", $"locales_version_{culture}");

                if (string.IsNullOrEmpty(resourcesJson) || string.IsNullOrEmpty(version))
                {
                    return false;
                }

                var resources = JsonSerializer.Deserialize<Dictionary<string, string>>(resourcesJson);

                if (resources != null && version != null)
                {
                    _resources[culture] = resources;
                    _versions[culture] = version;
                    return true;
                }
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "Failed to load resources from localStorage for culture: {Culture}", culture);
            }

            return false;
        }

        /// <summary>
        /// 从服务器更新获取文化语言数据
        /// </summary>
        /// <param name="culture"></param>
        /// <returns></returns>
        private async Task<bool> LoadFromServer(string culture)
        {
            try
            {
                var response = await _httpService.Get<ApiResult<LocalizationFile>>($"/api/localeresource/resources/{culture}");
                if (response.Success)
                {
                    _resources[culture] = response.Data.Translations;
                    _versions[culture] = response.Data.ResourceVersion;
                    // 保存到localStorage
                    await SaveToLocalStorage(culture, response.Data.Translations, response.Data.ResourceVersion);
                    ResourcesUpdated?.Invoke(this, culture);
                    return true;
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Failed to load resources from server for culture: {Culture}", culture);
            }

            return false;
        }


        /// <summary>
        /// 根据版本信息上从服务器数据对比版本更新数据
        /// </summary>
        /// <param name="culture"></param>
        /// <returns></returns>
        private async Task<bool> CheckAndUpdateFromServer(string culture)
        {
            try
            {
                var currentVersion = await GetResourceVersionAsync(culture);
                var serverVersion = await GetServerVersion(culture);

                if (serverVersion != null && (currentVersion == null || serverVersion != currentVersion))
                {
                    _logger.LogInformation("Updating resources for culture: {Culture}", culture);
                    return await LoadFromServer(culture);
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Failed to check and update resources for culture: {Culture}", culture);
            }

            return false;
        }

        /// <summary>
        /// 从服务器获取当前多语言文化数据版本信息
        /// </summary>
        /// <param name="culture"></param>
        /// <returns></returns>
        private async Task<string?> GetServerVersion(string culture)
        {
            try
            {
                var api = $"/api/localeresource/version/{culture}";
                var result = await _httpService.Get<ApiResult<string>>(api);
                if (result.Success)
                {
                    return result.Data;
                }
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "Failed to get server version for culture: {Culture}", culture);
            }

            return null;
        }

        /// <summary>
        /// 获取存储在本地的文化语言版本信息
        /// </summary>
        /// <param name="culture"></param>
        /// <returns></returns>
        private async Task<string?> GetStoredVersion(string culture)
        {
            try
            {
                var version = await _jsRuntime.InvokeAsync<string?>("localStorage.getItem", $"locales_version_{culture}");
                if (!string.IsNullOrEmpty(version))
                {
                    return version;
                }
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "Failed to get stored version for culture: {Culture}", culture);
            }

            return null;
        }

        /// <summary>
        /// 存储版本和文化语言信息
        /// </summary>
        /// <param name="culture"></param>
        /// <param name="resources"></param>
        /// <param name="version"></param>
        /// <returns></returns>
        private async Task SaveToLocalStorage(string culture, Dictionary<string, string> resources, string version)
        {
            try
            {
                var resourcesJson = JsonSerializer.Serialize(resources);

                await _jsRuntime.InvokeVoidAsync("localStorage.setItem", $"locales_{culture}", resourcesJson);
                await _jsRuntime.InvokeVoidAsync("localStorage.setItem", $"locales_version_{culture}", version);
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "Failed to save resources to localStorage for culture: {Culture}", culture);
            }
        }

        /// <summary>
        /// 获取浏览器上的文化语言信息
        /// </summary>
        /// <returns></returns>
        private async Task<string> GetCurrentCultureAsync()
        {
            try
            {
                return await _jsRuntime.InvokeAsync<string>("blazorCulture.get");
            }
            catch
            {
                return "en-US"; // 默认文化
            }
        }

        public async ValueTask DisposeAsync()
        {
            _semaphore?.Dispose();
        }
    }
}
