using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Theriapolis.Core.Data;
using Theriapolis.Core.World;

namespace Theriapolis.Game.Rendering;

/// <summary>
/// Manages the biome tile textures used by the world-map renderer.
/// For Phase 0/1, all tiles are generated at runtime as flat-colour 32×32 squares
/// with a 1px darker border and a single centered letter.
/// Final art will replace these by swapping file contents; no code changes needed.
/// </summary>
public sealed class TileAtlas : IDisposable
{
    private readonly GraphicsDevice _gd;
    private readonly Dictionary<BiomeId, Texture2D> _textures = new();
    private readonly Dictionary<int, Texture2D> _settlementIcons = new(); // keyed by tier
    private SpriteFont? _font;
    private bool _disposed;

    public GraphicsDevice GraphicsDevice => _gd;

    // Fallback solid-color texture for any biome that has no dedicated entry
    private Texture2D? _fallback;

    public TileAtlas(GraphicsDevice gd)
    {
        _gd = gd;
    }

    /// <summary>
    /// Generate all placeholder textures from the loaded BiomeDef array.
    /// Call once after content is loaded.
    /// </summary>
    public void GeneratePlaceholders(BiomeDef[] biomes, SpriteFont? font = null)
    {
        _font = font;
        foreach (var def in biomes)
        {
            var biomeId = BiomeAssignHelper.ParseBiomeId(def.Id);
            if (_textures.ContainsKey(biomeId)) continue;
            _textures[biomeId] = MakeTile(def);
        }
        _fallback = MakeSolidColor(Color.HotPink); // obvious "missing art" colour
        GenerateSettlementIcons();
    }

    /// <summary>Returns the settlement icon texture for the given tier (1–5).</summary>
    public Texture2D GetSettlementIcon(int tier)
    {
        if (_settlementIcons.TryGetValue(tier, out var tex)) return tex;
        return _fallback ?? _textures.Values.First();
    }

    private void GenerateSettlementIcons()
    {
        // Tier 1: large gold diamond (capital)
        _settlementIcons[1] = MakeSettlementIcon(20, new Color(255, 215, 0), diamond: true);
        // Tier 2: white square (city)
        _settlementIcons[2] = MakeSettlementIcon(14, new Color(230, 230, 230), diamond: false);
        // Tier 3: light-blue circle (town)
        _settlementIcons[3] = MakeSettlementIcon(10, new Color(150, 200, 255), diamond: false);
        // Tier 4: pale dot (village)
        _settlementIcons[4] = MakeSettlementIcon(6,  new Color(200, 200, 200), diamond: false);
        // Tier 5 (PoI): small red circle
        _settlementIcons[5] = MakeSettlementIcon(5,  new Color(200, 60, 60),   diamond: false);
    }

    private Texture2D MakeSettlementIcon(int size, Color fill, bool diamond)
    {
        var tex    = new Texture2D(_gd, size, size);
        var pixels = new Color[size * size];
        float cx   = (size - 1) * 0.5f;
        float cy   = (size - 1) * 0.5f;

        for (int py = 0; py < size; py++)
        for (int px = 0; px < size; px++)
        {
            float nx = px - cx, ny = py - cy;
            bool inside = diamond
                ? (MathF.Abs(nx) + MathF.Abs(ny)) <= size * 0.5f
                : (nx * nx + ny * ny) <= (cx * cx);
            pixels[py * size + px] = inside ? fill : Color.Transparent;
        }

        tex.SetData(pixels);
        return tex;
    }

    /// <summary>Returns the texture for the given biome, falling back to the error texture.</summary>
    public Texture2D GetTile(BiomeId biome)
    {
        if (_textures.TryGetValue(biome, out var tex)) return tex;
        return _fallback ?? _textures.Values.First();
    }

    // ── Texture generation helpers ────────────────────────────────────────────

    private Texture2D MakeTile(BiomeDef def)
    {
        int size = Theriapolis.Core.C.WORLD_TILE_PIXELS;
        var (r, g, b) = def.ParsedColor();
        var fillColor = new Color(r, g, b);

        var tex    = new Texture2D(_gd, size, size);
        var pixels = new Color[size * size];
        Array.Fill(pixels, fillColor);

        tex.SetData(pixels);
        return tex;
    }

    private Texture2D MakeSolidColor(Color color)
    {
        int size   = Theriapolis.Core.C.WORLD_TILE_PIXELS;
        var tex    = new Texture2D(_gd, size, size);
        var pixels = new Color[size * size];
        Array.Fill(pixels, color);
        tex.SetData(pixels);
        return tex;
    }

    public void Dispose()
    {
        if (_disposed) return;
        _disposed = true;
        foreach (var tex in _textures.Values) tex.Dispose();
        foreach (var tex in _settlementIcons.Values) tex.Dispose();
        _fallback?.Dispose();
    }
}

/// <summary>Internal helper to avoid exposing the private static method on BiomeAssignStage.</summary>
internal static class BiomeAssignHelper
{
    public static BiomeId ParseBiomeId(string id)
        => Theriapolis.Core.World.Generation.Stages.BiomeAssignStage.ParseBiomeId(id);
}
