using Theriapolis.Core;
using Theriapolis.Core.World;
using Theriapolis.Core.World.Generation;
using Xunit;

namespace Theriapolis.Tests.Worldgen;

/// <summary>
/// Biome coverage sanity checks:
/// - No seed produces a map that is &gt;80% one biome.
/// - Each required non-ocean biome appears in at least 1% of land tiles.
/// </summary>
public sealed class BiomeCoverageTests : IClassFixture<WorldCache>
{
    private readonly WorldCache _cache;

    public BiomeCoverageTests(WorldCache cache) => _cache = cache;

    private Dictionary<BiomeId, int> CountBiomes(ulong seed)
    {
        var ctx = _cache.Get(seed);

        var counts = new Dictionary<BiomeId, int>();
        int W = C.WORLD_WIDTH_TILES, H = C.WORLD_HEIGHT_TILES;
        for (int ty = 0; ty < H; ty++)
        for (int tx = 0; tx < W; tx++)
        {
            var b = ctx.World.Tiles[tx, ty].Biome;
            counts.TryGetValue(b, out int c);
            counts[b] = c + 1;
        }
        return counts;
    }

    [Fact]
    public void NoBiomeDominatesMoreThan80Percent()
    {
        var counts = CountBiomes(0xCAFEBABEUL);
        int total  = C.WORLD_WIDTH_TILES * C.WORLD_HEIGHT_TILES;
        foreach (var (biome, count) in counts)
        {
            double pct = (double)count / total;
            Assert.True(pct < 0.80,
                $"Biome {biome} covers {pct:P1} of the map (limit 80%).");
        }
    }

    [Fact]
    public void RequiredBiomes_AppearInAtLeast1PercentOfLandTiles()
    {
        var counts = CountBiomes(0xCAFEBABEUL);
        int total  = C.WORLD_WIDTH_TILES * C.WORLD_HEIGHT_TILES;
        int oceanCount = counts.GetValueOrDefault(BiomeId.Ocean);
        int landTotal  = total - oceanCount;

        // These biomes must all be present and non-trivial
        BiomeId[] required =
        {
            BiomeId.Tundra,
            BiomeId.Boreal,
            BiomeId.TemperateDeciduous,
            BiomeId.TemperateGrassland,
            BiomeId.MountainAlpine,
            BiomeId.SubtropicalForest,
        };

        foreach (var biome in required)
        {
            int count = counts.GetValueOrDefault(biome);
            double pct = landTotal > 0 ? (double)count / landTotal : 0;
            Assert.True(pct >= 0.01,
                $"Required biome {biome} covers only {pct:P2} of land tiles (minimum 1%).");
        }
    }
}
