using Theriapolis.Core.World.Generation;

namespace Theriapolis.Tools.Commands;

/// <summary>
/// worldgen-hash --seed &lt;n&gt; [--data-dir &lt;dir&gt;]
///
/// Runs the full worldgen pipeline and prints the FNV-1a hashes of every
/// output channel (elevation, moisture, temperature, biomes, settlements,
/// polylines) plus the per-stage hash dictionary. Used as a determinism
/// oracle for the Godot port — the Godot host prints the same hashes,
/// they must match byte-for-byte.
/// </summary>
public static class WorldgenHash
{
    public static int Run(string[] args)
    {
        ulong seed = 12345;
        string dataDir = ResolveDataDir();

        for (int i = 0; i < args.Length; i++)
        {
            switch (args[i].ToLowerInvariant())
            {
                case "--seed":
                    if (i + 1 < args.Length)
                    {
                        string raw = args[++i];
                        seed = raw.StartsWith("0x", StringComparison.OrdinalIgnoreCase)
                            ? Convert.ToUInt64(raw[2..], 16)
                            : ulong.Parse(raw);
                    }
                    break;
                case "--data-dir":
                    if (i + 1 < args.Length) dataDir = args[++i];
                    break;
            }
        }

        if (!Directory.Exists(dataDir))
        {
            Console.Error.WriteLine($"Data directory not found: {dataDir}");
            return 1;
        }

        Console.WriteLine($"[worldgen-hash] seed=0x{seed:X} data-dir={dataDir}");
        var ctx = new WorldGenContext(seed, dataDir);
        WorldGenerator.RunAll(ctx);
        var w = ctx.World;

        Console.WriteLine($"[worldgen-hash] === FNV hashes ===");
        Console.WriteLine($"[worldgen-hash] elevation     = 0x{w.HashElevation():X16}");
        Console.WriteLine($"[worldgen-hash] moisture      = 0x{w.HashMoisture():X16}");
        Console.WriteLine($"[worldgen-hash] temperature   = 0x{w.HashTemperature():X16}");
        Console.WriteLine($"[worldgen-hash] biomes        = 0x{w.HashBiomes():X16}");
        Console.WriteLine($"[worldgen-hash] settlements   = 0x{w.HashSettlements():X16}");
        Console.WriteLine($"[worldgen-hash] polylines     = 0x{w.HashPolylines():X16}");
        Console.WriteLine($"[worldgen-hash] === Per-stage hashes ({w.StageHashes.Count}) ===");
        foreach (var kv in w.StageHashes.OrderBy(k => k.Key, StringComparer.Ordinal))
            Console.WriteLine($"[worldgen-hash] {kv.Key,-32} = 0x{kv.Value:X16}");
        return 0;
    }

    private static string ResolveDataDir()
    {
        string local = Path.Combine(AppContext.BaseDirectory, "Data");
        if (Directory.Exists(local)) return local;

        string? dir = AppContext.BaseDirectory.TrimEnd(
            Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
        for (int i = 0; i < 6; i++)
        {
            if (dir is null) break;
            string candidate = Path.Combine(dir, "Content", "Data");
            if (Directory.Exists(candidate)) return candidate;
            dir = Path.GetDirectoryName(dir);
        }

        return local;
    }
}
