using System.Net;
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
using DorkNet.Server.Controllers.API.Avatar.V4;
using DorkNet.Server.Data;
using DorkNet.Server.Services;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
namespace DorkNet.Server.Tests;
///
/// Wire contract of the 2023-03-21 client's outfit / wardrobe menu, as read
/// from RecNet.Runtime ISIL: saved-outfit slots (BEPMJICDNDD via converter
/// IMMOJHBENFI), the custom-avatar-item gates the menu queries when it opens,
/// the locked-item lookup, the owned list's per-entry ids, and the gift
/// generate call the menu's gift flow makes.
///
public sealed class OutfitMenu2023Tests : IClassFixture
{
private readonly DorkNetServerFactory _factory;
public OutfitMenu2023Tests(DorkNetServerFactory factory) => _factory = factory;
[Fact]
public async Task Creation_allowed_gate_is_a_success_error_envelope()
{
// MPBLNLMCEDL.GGMDLMLJDDK parses DJMHAFPGLLN {Success, Error}
// (LMCCNLLHLCJ.txt:191-254); a bare boolean is what logged
// "Failed to query if local account can create Custom Avatar Items".
using var setup = ApiClient();
var player = await GameClientSessionFactory.CreateAsync(setup, _factory.ApexDomain);
using var client = ApiClient(player);
var body = await GetJsonAsync(client, "/api/customAvatarItems/v1/isCreationAllowedForAccount");
Assert.Equal(JsonValueKind.Object, body.ValueKind);
Assert.Equal(JsonValueKind.True, body.GetProperty("Success").ValueKind);
Assert.Equal(JsonValueKind.Null, body.GetProperty("Error").ValueKind);
}
[Fact]
public async Task Sibling_gates_and_min_price_are_bare_scalars()
{
using var client = ApiClient();
Assert.Equal(JsonValueKind.True, (await GetJsonAsync(client, "/api/customAvatarItems/v1/isCreationEnabled")).ValueKind);
Assert.Equal(JsonValueKind.True, (await GetJsonAsync(client, "/api/customAvatarItems/v1/isRenderingEnabled")).ValueKind);
// b__69_0(Int32 minimumPrice) — a bare integer.
var min = await GetJsonAsync(client, "/api/customAvatarItems/v1/minPriceForPublicItem");
Assert.Equal(JsonValueKind.Number, min.ValueKind);
Assert.True(min.GetInt32() > 0);
}
[Fact]
public async Task Saved_outfit_round_trips_every_client_key()
{
using var setup = ApiClient();
var player = await GameClientSessionFactory.CreateAsync(setup, _factory.ApexDomain);
using var client = ApiClient(player);
var shirt = Guid.NewGuid();
// Exactly what the client's writer (IMMOJHBENFI.txt:781-910) emits.
var outfit = new Dictionary
{
["Slot"] = 3,
["PreviewImageName"] = "preview-3.jpg",
["OutfitSelections"] = "",
["OutfitSelectionsV2"] = "{\"v\":2,\"items\":[\"a\",\"b\"]}",
["FaceFeatures"] = "{\"ver\":3}",
["SkinColor"] = "skin-guid",
["HairColor"] = "hair-guid",
["CustomAvatarItems"] = new[] { new { CustomAvatarItemId = shirt, BodyPart = 2 } },
};
await PostJsonAsync(client, "/api/avatar/v3/saved/set", outfit);
var list = await GetJsonAsync(client, "/api/avatar/v3/saved");
var saved = list.EnumerateArray().Single(o => o.GetProperty("Slot").GetInt32() == 3);
Assert.Equal("preview-3.jpg", saved.GetProperty("PreviewImageName").GetString());
Assert.Equal("{\"v\":2,\"items\":[\"a\",\"b\"]}", saved.GetProperty("OutfitSelectionsV2").GetString());
Assert.Equal("{\"ver\":3}", saved.GetProperty("FaceFeatures").GetString());
Assert.Equal("skin-guid", saved.GetProperty("SkinColor").GetString());
Assert.Equal("hair-guid", saved.GetProperty("HairColor").GetString());
var items = saved.GetProperty("CustomAvatarItems");
Assert.Equal(1, items.GetArrayLength());
Assert.Equal(shirt, items[0].GetProperty("CustomAvatarItemId").GetGuid());
Assert.Equal(2, items[0].GetProperty("BodyPart").GetInt32());
// Overwriting the slot replaces it rather than adding a second row.
outfit["OutfitSelectionsV2"] = "{\"v\":2,\"items\":[\"c\"]}";
outfit["CustomAvatarItems"] = Array.Empty