using System.Text.Encodings.Web;
using System.Text.Json;

namespace TakeoutSaaS.Domain.Dictionary.ValueObjects;

/// <summary>
/// 多语言字典值对象，封装语言键值映射。
/// </summary>
public sealed class I18nValue : IEquatable<I18nValue>
{
    private static readonly string[] FallbackLocales = ["zh-CN", "en"];
    private static readonly JsonSerializerOptions JsonOptions = new(JsonSerializerDefaults.Web)
    {
        Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
    };
    private readonly Dictionary<string, string> _values;

    /// <summary>
    /// 初始化多语言值。
    /// </summary>
    /// <param name="values">语言键值映射。</param>
    /// <exception cref="ArgumentException">传入值为空或无有效条目时抛出。</exception>
    public I18nValue(IDictionary<string, string> values)
    {
        if (values == null)
        {
            throw new ArgumentNullException(nameof(values));
        }

        _values = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
        foreach (var (key, value) in values)
        {
            if (string.IsNullOrWhiteSpace(key) || string.IsNullOrWhiteSpace(value))
            {
                continue;
            }

            _values[key.Trim()] = value.Trim();
        }

        if (_values.Count == 0)
        {
            throw new ArgumentException("I18nValue requires at least one non-empty entry.", nameof(values));
        }
    }

    /// <summary>
    /// 语言键值只读视图。
    /// </summary>
    public IReadOnlyDictionary<string, string> Values => _values;

    /// <summary>
    /// 获取指定语言值，支持回退策略。
    /// </summary>
    /// <param name="locale">语言标识。</param>
    /// <returns>匹配语言值。</returns>
    public string Extract(string? locale)
    {
        if (!string.IsNullOrWhiteSpace(locale) && _values.TryGetValue(locale, out var value))
        {
            return value;
        }

        foreach (var fallback in FallbackLocales)
        {
            if (_values.TryGetValue(fallback, out var fallbackValue))
            {
                return fallbackValue;
            }
        }

        return _values.Values.First();
    }

    /// <summary>
    /// 转换为普通字典。
    /// </summary>
    public Dictionary<string, string> ToDictionary()
        => new(_values, StringComparer.OrdinalIgnoreCase);

    /// <summary>
    /// 转换为 JSON 字符串。
    /// </summary>
    public string ToJson()
        => JsonSerializer.Serialize(_values, JsonOptions);

    /// <summary>
    /// 从 JSON 字符串解析多语言值。
    /// </summary>
    public static I18nValue FromJson(string json)
    {
        if (string.IsNullOrWhiteSpace(json))
        {
            throw new ArgumentException("JSON payload is required.", nameof(json));
        }

        var values = JsonSerializer.Deserialize<Dictionary<string, string>>(json, JsonOptions) ?? new Dictionary<string, string>();
        return new I18nValue(values);
    }

    /// <inheritdoc />
    public bool Equals(I18nValue? other)
    {
        if (other == null)
        {
            return false;
        }

        if (ReferenceEquals(this, other))
        {
            return true;
        }

        if (_values.Count != other._values.Count)
        {
            return false;
        }

        foreach (var (key, value) in _values)
        {
            if (!other._values.TryGetValue(key, out var otherValue))
            {
                return false;
            }

            if (!string.Equals(value, otherValue, StringComparison.Ordinal))
            {
                return false;
            }
        }

        return true;
    }

    /// <inheritdoc />
    public override bool Equals(object? obj)
        => obj is I18nValue other && Equals(other);

    /// <inheritdoc />
    public override int GetHashCode()
    {
        var hash = new HashCode();
        foreach (var pair in _values.OrderBy(item => item.Key, StringComparer.OrdinalIgnoreCase))
        {
            hash.Add(pair.Key, StringComparer.OrdinalIgnoreCase);
            hash.Add(pair.Value, StringComparer.Ordinal);
        }

        return hash.ToHashCode();
    }
}
