using System.Text.Json.Serialization;

namespace NeonSprawl.Server.Game.AbilityInput;

/// <summary>Canonical hotbar loadout payload returned by loadout APIs (NEO-29).</summary>
public sealed class HotbarLoadoutResponse
{
    public const int CurrentSchemaVersion = 1;
    public const int SlotCountV1 = 8;

    [JsonPropertyName("schemaVersion")]
    public int SchemaVersion { get; init; } = CurrentSchemaVersion;

    [JsonPropertyName("playerId")]
    public required string PlayerId { get; init; }

    [JsonPropertyName("slotCount")]
    public int SlotCount { get; init; } = SlotCountV1;

    /// <summary>Always includes v1 slots 0..7 in ascending order.</summary>
    [JsonPropertyName("slots")]
    public required IReadOnlyList<HotbarSlotStateJson> Slots { get; init; }
}

/// <summary>POST body for hotbar loadout updates.</summary>
public sealed class HotbarLoadoutUpdateRequest
{
    public const int CurrentSchemaVersion = 1;

    [JsonPropertyName("schemaVersion")]
    public int SchemaVersion { get; init; }

    /// <summary>
    /// Requested slot bindings to apply. Slot entries are upserts; unspecified slots keep previous values.
    /// </summary>
    [JsonPropertyName("slots")]
    public IReadOnlyList<HotbarSlotBindingJson>? Slots { get; init; }
}

/// <summary>POST response for hotbar updates (applied or denied).</summary>
public sealed class HotbarLoadoutUpdateResponse
{
    public const int CurrentSchemaVersion = 1;

    [JsonPropertyName("schemaVersion")]
    public int SchemaVersion { get; init; } = CurrentSchemaVersion;

    [JsonPropertyName("updated")]
    public bool Updated { get; init; }

    [JsonPropertyName("loadout")]
    public required HotbarLoadoutResponse Loadout { get; init; }

    /// <summary>Required on deny responses; omitted when <see cref="Updated"/> is true.</summary>
    [JsonPropertyName("reasonCode")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? ReasonCode { get; init; }
}

/// <summary>Wire shape for an individual slot state in GET/POST responses.</summary>
public sealed class HotbarSlotStateJson
{
    [JsonPropertyName("slotIndex")]
    public required int SlotIndex { get; init; }

    /// <summary>Canonical lowercase ability id or null when the slot is unbound.</summary>
    [JsonPropertyName("abilityId")]
    [JsonIgnore(Condition = JsonIgnoreCondition.Never)]
    public string? AbilityId { get; init; }
}

/// <summary>Wire shape for an individual slot update in POST requests.</summary>
public sealed class HotbarSlotBindingJson
{
    [JsonPropertyName("slotIndex")]
    public int SlotIndex { get; init; }

    [JsonPropertyName("abilityId")]
    public string? AbilityId { get; init; }
}
