using System.Text.Json.Serialization;

namespace Theriapolis.Core.Data;

/// <summary>
/// A single cell in the 32×32 authored macro-template grid.
/// Defines the biome character and generation constraints for a 32×32-tile region.
/// </summary>
public sealed class MacroCell
{
    [JsonPropertyName("biome_type")]
    public string BiomeType { get; set; } = "temperate_grassland";

    [JsonPropertyName("clade_affinities")]
    public string[] CladeAffinities { get; set; } = Array.Empty<string>();

    [JsonPropertyName("development")]
    public string Development { get; set; } = "agricultural";

    /// <summary>strong | moderate | weak | nominal</summary>
    [JsonPropertyName("covenant")]
    public string Covenant { get; set; } = "moderate";

    // Elevation constraints (0–1 range). Floor = minimum, Ceiling = maximum.
    [JsonPropertyName("elevation_floor")]
    public float ElevationFloor { get; set; } = 0f;

    [JsonPropertyName("elevation_ceiling")]
    public float ElevationCeiling { get; set; } = 1f;

    // Moisture constraints
    [JsonPropertyName("moisture_floor")]
    public float MoistureFloor { get; set; } = 0f;

    [JsonPropertyName("moisture_ceiling")]
    public float MoistureCeiling { get; set; } = 1f;

    // Temperature modifiers (added to base latitude temperature)
    [JsonPropertyName("temp_modifier")]
    public float TempModifier { get; set; } = 0f;
}

/// <summary>Root structure of macro_template.json.</summary>
public sealed class MacroTemplate
{
    [JsonPropertyName("width")]
    public int Width { get; set; } = C.MACRO_GRID_WIDTH;

    [JsonPropertyName("height")]
    public int Height { get; set; } = C.MACRO_GRID_HEIGHT;

    [JsonPropertyName("default_cell")]
    public MacroCell DefaultCell { get; set; } = new();

    [JsonPropertyName("regions")]
    public MacroRegion[] Regions { get; set; } = Array.Empty<MacroRegion>();

    /// <summary>Expand regions into a flat [width, height] grid. Later regions overwrite earlier ones.</summary>
    public MacroCell[,] Build()
    {
        var grid = new MacroCell[Width, Height];
        // Fill with default
        for (int y = 0; y < Height; y++)
            for (int x = 0; x < Width; x++)
                grid[x, y] = DefaultCell;
        // Paint regions in order (later regions win)
        foreach (var r in Regions)
        {
            var cell = r.ToCell();
            int x1 = Math.Min(r.X + r.W, Width);
            int y1 = Math.Min(r.Y + r.H, Height);
            for (int y = Math.Max(0, r.Y); y < y1; y++)
                for (int x = Math.Max(0, r.X); x < x1; x++)
                    grid[x, y] = cell;
        }
        return grid;
    }
}

/// <summary>A rectangular block in the macro template, painted over the default.</summary>
public sealed class MacroRegion
{
    [JsonPropertyName("x")] public int X { get; set; }
    [JsonPropertyName("y")] public int Y { get; set; }
    [JsonPropertyName("w")] public int W { get; set; }
    [JsonPropertyName("h")] public int H { get; set; }
    /// <summary>Human-readable annotation in the JSON file — ignored at runtime.</summary>
    [JsonPropertyName("comment")] public string? Comment { get; set; }

    [JsonPropertyName("biome_type")]       public string BiomeType { get; set; } = "temperate_grassland";
    [JsonPropertyName("clade_affinities")] public string[] CladeAffinities { get; set; } = Array.Empty<string>();
    [JsonPropertyName("development")]      public string Development { get; set; } = "agricultural";
    [JsonPropertyName("covenant")]         public string Covenant { get; set; } = "moderate";
    [JsonPropertyName("elevation_floor")]  public float ElevationFloor { get; set; } = 0f;
    [JsonPropertyName("elevation_ceiling")]public float ElevationCeiling { get; set; } = 1f;
    [JsonPropertyName("moisture_floor")]   public float MoistureFloor { get; set; } = 0f;
    [JsonPropertyName("moisture_ceiling")] public float MoistureCeiling { get; set; } = 1f;
    [JsonPropertyName("temp_modifier")]    public float TempModifier { get; set; } = 0f;

    public MacroCell ToCell() => new()
    {
        BiomeType        = BiomeType,
        CladeAffinities  = CladeAffinities,
        Development      = Development,
        Covenant         = Covenant,
        ElevationFloor   = ElevationFloor,
        ElevationCeiling = ElevationCeiling,
        MoistureFloor    = MoistureFloor,
        MoistureCeiling  = MoistureCeiling,
        TempModifier     = TempModifier,
    };
}
