using System.Text.Json.Serialization;

namespace NeonSprawl.Server.Game.Skills;

/// <summary>POST body for applying one skill XP grant (NEO-38).</summary>
public sealed class SkillProgressionGrantRequest
{
    public const int CurrentSchemaVersion = 1;

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

    [JsonPropertyName("skillId")]
    public required string SkillId { get; init; }

    [JsonPropertyName("amount")]
    public int Amount { get; init; }

    /// <remarks>Validated against target skill&apos;s <c>allowedXpSourceKinds</c> (ordinal ignore-case).</remarks>
    [JsonPropertyName("sourceKind")]
    public required string SourceKind { get; init; }
}

/// <summary>POST responses for progression grants — success (<see cref="Granted"/>) or structured deny (<see cref="ReasonCode"/>).</summary>
public sealed class SkillProgressionGrantResponse
{
    public const int CurrentSchemaVersion = 1;

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

    [JsonPropertyName("granted")]
    public bool Granted { get; init; }

    /// <remarks>Set when <see cref="Granted"/> is <c>false</c>; stable snake_case values (see README).</remarks>
    [JsonPropertyName("reasonCode")]
    public string? ReasonCode { get; init; }

    [JsonPropertyName("progression")]
    public required SkillProgressionSnapshotResponse Progression { get; init; }

    /// <remarks>Present on success only; empty array when XP changed but level did not.</remarks>
    [JsonPropertyName("levelUps")]
    public required IReadOnlyList<SkillLevelUpJson> LevelUps { get; init; }
}

/// <summary>One skill crossed a level boundary on this grant (<c>previousLevel</c> &lt; <c>newLevel</c>).</summary>
public sealed class SkillLevelUpJson
{
    [JsonPropertyName("skillId")]
    public required string SkillId { get; init; }

    [JsonPropertyName("previousLevel")]
    public int PreviousLevel { get; init; }

    [JsonPropertyName("newLevel")]
    public int NewLevel { get; init; }
}
