namespace Theriapolis.Core.Rules.Stats;

/// <summary>
/// Body-size category from clades.md. Determines tactical-tile footprint,
/// reach, equipment fit, and grappling rules.
/// </summary>
public enum SizeCategory : byte
{
    Tiny        = 0,  // reserved; no Phase 5 species uses this
    Small       = 1,  // rabbit-folk, housecat-folk, ferret-folk
    Medium      = 2,  // fox-folk, deer-folk, ram-folk, leopard-folk, badger-folk, hare-folk
    MediumLarge = 3,  // wolf-folk, elk-folk, lion-folk, wolverine-folk, coyote-folk
    Large       = 4,  // brown bear-folk, polar bear-folk, moose-folk, bull-folk, bison-folk
    Huge        = 5,  // reserved; no Phase 5 species uses this
}

public static class SizeExtensions
{
    /// <summary>Tactical-tile footprint per side (1 = 1×1, 2 = 2×2).</summary>
    public static int FootprintTiles(this SizeCategory s) => s switch
    {
        SizeCategory.Tiny        => 1,
        SizeCategory.Small       => 1,
        SizeCategory.Medium      => 1,
        SizeCategory.MediumLarge => 1,   // counts as Large for grappling/carrying only
        SizeCategory.Large       => 2,
        SizeCategory.Huge        => 3,
        _ => throw new ArgumentOutOfRangeException(nameof(s)),
    };

    /// <summary>Default melee reach in tactical tiles (weapon-modifiable).</summary>
    public static int DefaultReachTiles(this SizeCategory s) => s switch
    {
        SizeCategory.Tiny        => 1,
        SizeCategory.Small       => 1,
        SizeCategory.Medium      => 1,
        SizeCategory.MediumLarge => 1,
        SizeCategory.Large       => 2,
        SizeCategory.Huge        => 3,
        _ => throw new ArgumentOutOfRangeException(nameof(s)),
    };

    /// <summary>Carrying-capacity multiplier per equipment.md (Small ½×, Large 2×).</summary>
    public static float CarryCapacityMult(this SizeCategory s) => s switch
    {
        SizeCategory.Tiny        => 0.25f,
        SizeCategory.Small       => 0.5f,
        SizeCategory.Medium      => 1.0f,
        SizeCategory.MediumLarge => 1.0f,  // Medium frame, Large for grappling
        SizeCategory.Large       => 2.0f,
        SizeCategory.Huge        => 4.0f,
        _ => throw new ArgumentOutOfRangeException(nameof(s)),
    };

    /// <summary>Parses a snake_case JSON value (e.g. "medium_large") into a SizeCategory.</summary>
    public static SizeCategory FromJson(string? raw) => raw switch
    {
        "tiny"          => SizeCategory.Tiny,
        "small"         => SizeCategory.Small,
        "medium"        => SizeCategory.Medium,
        "medium_large"  => SizeCategory.MediumLarge,
        "large"         => SizeCategory.Large,
        "huge"          => SizeCategory.Huge,
        _ => throw new ArgumentException($"Unknown size category: '{raw}'"),
    };
}
