using System.Globalization;
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Text.Unicode;
using Baya.Application.Contracts.Common;
using Baya.Application.Models.Catalog;

namespace Baya.Application.Common;

/// <summary>
/// Canonical implementation of <see cref="IVariantSnapshotSerializer"/>. Emits a stable, camelCase JSON
/// object carrying the category id + labels, each resolved <c>(group label, value label)</c>, the price
/// (as a string of digits), price unit, session count, display name, and the variant id. Property order is
/// fixed (declaration order) so the output is deterministic for a given input.
/// </summary>
public sealed class VariantSnapshotSerializer : IVariantSnapshotSerializer
{
    private static readonly JsonSerializerOptions Options = new()
    {
        PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
        DefaultIgnoreCondition = JsonIgnoreCondition.Never,
        // Persian labels must land in the snapshot as readable text, not \uXXXX escapes; the encoder still
        // escapes the HTML-sensitive ASCII characters so the stored JSON stays safe to embed.
        Encoder = JavaScriptEncoder.Create(UnicodeRanges.All),
        WriteIndented = false
    };

    public string Serialize(VariantSnapshot snapshot)
    {
        // Money crosses the snapshot as a string of IRR-Rial digits (integer money, no floats). Invariant
        // culture so the digits are always ASCII regardless of the ambient locale.
        var payload = new
        {
            variantId = snapshot.VariantId,
            serviceCategoryId = snapshot.ServiceCategoryId,
            categoryNameFa = snapshot.CategoryNameFa,
            categoryNameEn = snapshot.CategoryNameEn,
            price = snapshot.Price.ToString(CultureInfo.InvariantCulture),
            priceUnit = snapshot.PriceUnit,
            sessionCount = snapshot.SessionCount,
            displayName = snapshot.DisplayName,
            options = snapshot.Options.Select(o => new
            {
                o.OptionGroupId,
                o.GroupNameFa,
                o.GroupNameEn,
                o.OptionValueId,
                o.ValueNameFa,
                o.ValueNameEn
            })
        };

        return JsonSerializer.Serialize(payload, Options);
    }
}
