using System.Text.Json.Serialization;

namespace Theriapolis.Core.Data;

/// <summary>
/// Phase 6 M0 — definition of a single stampable building (inn, shop, house,
/// magistrate, etc.). Loaded from <c>Content/Data/building_templates/*.json</c>.
///
/// A template describes:
///   - The building's footprint in tactical tiles.
///   - Where doors sit on the perimeter.
///   - Which interior cells get specific furniture (counter, bed, hearth, sign).
///   - Which "roles" the building offers (innkeeper, shopkeeper, guard) and
///     where each role's resident NPC stands when the player walks in.
///
/// Stamping draws walls along the perimeter, floors inside, doors at the
/// declared door cells, and decorations at the declared deco cells. Spawn
/// records for roles are emitted into the chunk's <see cref="Tactical.TacticalSpawn"/>
/// list as <see cref="Tactical.SpawnKind.Resident"/> (Phase 6 M1).
/// </summary>
public sealed record BuildingTemplateDef
{
    [JsonPropertyName("id")]
    public string Id { get; init; } = "";

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

    /// <summary>Footprint width in tactical tiles. Includes perimeter walls.</summary>
    [JsonPropertyName("footprint_w_tiles")]
    public int FootprintWTiles { get; init; } = 1;

    /// <summary>Footprint height in tactical tiles. Includes perimeter walls.</summary>
    [JsonPropertyName("footprint_h_tiles")]
    public int FootprintHTiles { get; init; } = 1;

    /// <summary>Lowest settlement tier this template is eligible for (4 = village+).</summary>
    [JsonPropertyName("min_tier_eligible")]
    public int MinTierEligible { get; init; } = 5;

    /// <summary>Door positions in template-local coords (0..W-1, 0..H-1).</summary>
    [JsonPropertyName("doors")]
    public BuildingDoor[] Doors { get; init; } = Array.Empty<BuildingDoor>();

    /// <summary>Decorations in template-local coords.</summary>
    [JsonPropertyName("decos")]
    public BuildingDecoPlacement[] Decos { get; init; } = Array.Empty<BuildingDecoPlacement>();

    /// <summary>Resident roles (innkeeper, shopkeeper, guard, ...).</summary>
    [JsonPropertyName("roles")]
    public BuildingRole[] Roles { get; init; } = Array.Empty<BuildingRole>();

    /// <summary>
    /// Optional biome filter. Empty = eligible everywhere. Otherwise the
    /// settlement's home tile must be one of these biome ids.
    /// </summary>
    [JsonPropertyName("biome_filter")]
    public string[] BiomeFilter { get; init; } = Array.Empty<string>();

    /// <summary>Selection weight in procedural Tier 2–5 layout rolls. Default 1.0.</summary>
    [JsonPropertyName("weight")]
    public float Weight { get; init; } = 1f;

    /// <summary>"civic" / "shop" / "house" / "inn" / "infrastructure" — used by procedural layout role mix.</summary>
    [JsonPropertyName("category")]
    public string Category { get; init; } = "house";
}

public sealed record BuildingDoor
{
    [JsonPropertyName("x")]
    public int X { get; init; }

    [JsonPropertyName("y")]
    public int Y { get; init; }

    /// <summary>Compass facing: "N" / "E" / "S" / "W". Door always sits on a perimeter cell.</summary>
    [JsonPropertyName("facing")]
    public string Facing { get; init; } = "S";
}

public sealed record BuildingDecoPlacement
{
    [JsonPropertyName("x")]
    public int X { get; init; }

    [JsonPropertyName("y")]
    public int Y { get; init; }

    /// <summary>Deco kind name: "counter" / "bed" / "hearth" / "sign".</summary>
    [JsonPropertyName("deco")]
    public string Deco { get; init; } = "";
}

public sealed record BuildingRole
{
    /// <summary>Role tag inside the template (e.g. "innkeeper", "shopkeeper", "guard").</summary>
    [JsonPropertyName("tag")]
    public string Tag { get; init; } = "";

    /// <summary>Spawn point in template-local coords. Must be an interior cell.</summary>
    [JsonPropertyName("spawn_at")]
    public int[] SpawnAt { get; init; } = new[] { 1, 1 };

    /// <summary>True if this role may be omitted in a procedural layout (slot left empty).</summary>
    [JsonPropertyName("optional")]
    public bool Optional { get; init; } = false;
}
