using System.Text.Json.Serialization;

namespace Theriapolis.Core.Data;

/// <summary>
/// Immutable species (subrace-equivalent) record loaded from species.json.
/// Refines the parent <see cref="CladeDef"/>: adds a body size, additional
/// ability mods, species-specific traits, and species-specific detriments.
/// </summary>
public sealed record SpeciesDef
{
    [JsonPropertyName("id")]
    public string Id { get; init; } = "";

    [JsonPropertyName("clade_id")]
    public string CladeId { get; init; } = "";

    [JsonPropertyName("name")]
    public string Name { get; init; } = "";

    /// <summary>Codex-voice species description: usually the doc's italicized
    /// blockquote followed by a one-sentence physical/cultural summary.
    /// Surfaced on the Step 1 card.</summary>
    [JsonPropertyName("description")]
    public string Description { get; init; } = "";

    /// <summary>Body size category, snake_case (small / medium / medium_large / large).</summary>
    [JsonPropertyName("size")]
    public string Size { get; init; } = "medium";

    /// <summary>Additional ability mods on top of the clade's mods.</summary>
    [JsonPropertyName("ability_mods")]
    public Dictionary<string, int> AbilityMods { get; init; } = new();

    /// <summary>Base movement speed in feet per turn (5 ft. = 1 tactical tile per d20 standard).</summary>
    [JsonPropertyName("base_speed_ft")]
    public int BaseSpeedFt { get; init; } = 30;

    [JsonPropertyName("traits")]
    public TraitDef[] Traits { get; init; } = Array.Empty<TraitDef>();

    [JsonPropertyName("detriments")]
    public TraitDef[] Detriments { get; init; } = Array.Empty<TraitDef>();

    /// <summary>
    /// "sex" (male/female) or "lineage" (e.g. sheep/goat for Ram-Folk).
    /// Empty when the species has no variants. Determines how the variant
    /// is resolved: sex-axis is auto-keyed off character Sex (purebred) or
    /// parent role for hybrids (sire = male, dam = female); lineage-axis
    /// requires an explicit per-species pick.
    /// </summary>
    [JsonPropertyName("variant_axis")]
    public string VariantAxis { get; init; } = "";

    /// <summary>
    /// Variant entries layered onto the species' base traits/detriments.
    /// The variant's id keys it: for sex-axis variants, "male" or "female";
    /// for lineage variants, the lineage tag (e.g. "sheep", "goat").
    /// Empty when the species has no variants.
    /// </summary>
    [JsonPropertyName("variants")]
    public SpeciesVariantDef[] Variants { get; init; } = Array.Empty<SpeciesVariantDef>();
}

/// <summary>
/// One sex- or lineage-keyed variant of a species. Layered on top of the
/// base species' traits and detriments — the player ends up with both
/// sets, not one or the other.
/// </summary>
public sealed record SpeciesVariantDef
{
    [JsonPropertyName("id")]
    public string Id { get; init; } = "";

    [JsonPropertyName("name")]
    public string Name { get; init; } = "";

    [JsonPropertyName("traits")]
    public TraitDef[] Traits { get; init; } = Array.Empty<TraitDef>();

    [JsonPropertyName("detriments")]
    public TraitDef[] Detriments { get; init; } = Array.Empty<TraitDef>();
}
