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

namespace Theriapolis.Tools.Commands;

/// <summary>
/// settlement-report --seed &lt;n&gt; [--data-dir &lt;dir&gt;]
///
/// Runs the full pipeline and prints a human-readable settlement report:
/// narrative anchors, tier breakdown, economy distribution, and PoI list.
/// </summary>
public static class SettlementReport
{
    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];
                        if (raw.StartsWith("0x", StringComparison.OrdinalIgnoreCase))
                            seed = Convert.ToUInt64(raw[2..], 16);
                        else
                            seed = ulong.Parse(raw);
                    }
                    break;
                case "--data-dir":
                    if (i + 1 < args.Length) dataDir = args[++i];
                    break;
            }
        }

        Console.WriteLine($"[settlement-report] seed=0x{seed:X} data-dir={dataDir}");

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

        var ctx = new WorldGenContext(seed, dataDir)
        {
            ProgressCallback = (name, _) => Console.Write($"\r  Running {name,-28}   "),
            Log = _ => { }, // suppress detailed logs
        };

        WorldGenerator.RunAll(ctx);
        Console.WriteLine("\r                                                    ");

        var world = ctx.World;
        var ss    = world.Settlements;

        if (ss.Count == 0)
        {
            Console.WriteLine("No settlements generated.");
            return 0;
        }

        // ── Narrative anchors ─────────────────────────────────────────────────
        Console.WriteLine("═══════════════════════════════════════════════════════");
        Console.WriteLine(" NARRATIVE ANCHORS");
        Console.WriteLine("═══════════════════════════════════════════════════════");
        foreach (var s in ss.Where(s => s.Anchor.HasValue).OrderBy(s => s.Anchor))
        {
            Console.WriteLine($"  [{s.Anchor}]");
            Console.WriteLine($"    Name     : {s.Name}");
            Console.WriteLine($"    Tier     : {s.Tier}");
            Console.WriteLine($"    Position : ({s.TileX}, {s.TileY})");
            Console.WriteLine($"    Economy  : {s.Economy}");
            Console.WriteLine($"    Wealth   : {s.WealthLevel:F3}");
            Console.WriteLine($"    Pop      : ~{s.Population}");
            Console.WriteLine($"    River    : {s.IsOnRiver}");
            Console.WriteLine($"    Rail     : {s.HasRailStation}");
            Console.WriteLine();
        }

        // ── Tier breakdown ────────────────────────────────────────────────────
        Console.WriteLine("═══════════════════════════════════════════════════════");
        Console.WriteLine(" SETTLEMENTS BY TIER");
        Console.WriteLine("═══════════════════════════════════════════════════════");
        for (int tier = 1; tier <= 4; tier++)
        {
            var ts = ss.Where(s => s.Tier == tier && !s.IsPoi).ToList();
            if (ts.Count == 0) continue;
            Console.WriteLine($"  Tier {tier} ({ts.Count}):");
            foreach (var s in ts.OrderBy(s => s.Name))
            {
                string anchor = s.Anchor.HasValue ? $" [{s.Anchor}]" : "";
                Console.WriteLine($"    ({s.TileX,4},{s.TileY,4}) {s.Name,-24}{anchor}");
                Console.WriteLine($"      Economy={s.Economy,-14} Gov={s.Governance,-16} Wealth={s.WealthLevel:F2}");
            }
        }
        Console.WriteLine();

        // ── Economy distribution ──────────────────────────────────────────────
        Console.WriteLine("═══════════════════════════════════════════════════════");
        Console.WriteLine(" ECONOMY DISTRIBUTION (Tier 1-4)");
        Console.WriteLine("═══════════════════════════════════════════════════════");
        var econGroups = ss.Where(s => !s.IsPoi)
            .GroupBy(s => s.Economy)
            .OrderByDescending(g => g.Count());
        foreach (var g in econGroups)
            Console.WriteLine($"  {g.Key,-18}: {g.Count(),3}");
        Console.WriteLine();

        // ── PoI list ──────────────────────────────────────────────────────────
        var pois = ss.Where(s => s.IsPoi).ToList();
        if (pois.Count > 0)
        {
            Console.WriteLine("═══════════════════════════════════════════════════════");
            Console.WriteLine($" POINTS OF INTEREST ({pois.Count})");
            Console.WriteLine("═══════════════════════════════════════════════════════");
            foreach (var p in pois.OrderBy(p => p.PoiType).ThenBy(p => p.TileX))
                Console.WriteLine($"  ({p.TileX,4},{p.TileY,4}) {p.Name,-24} [{p.PoiType}]");
            Console.WriteLine();
        }

        // ── Linear features ────────────────────────────────────────────────────
        Console.WriteLine("═══════════════════════════════════════════════════════");
        Console.WriteLine(" LINEAR FEATURES");
        Console.WriteLine("═══════════════════════════════════════════════════════");
        Console.WriteLine($"  Rivers : {world.Rivers.Count}");
        Console.WriteLine($"  Roads  : {world.Roads.Count}");
        Console.WriteLine($"  Rails  : {world.Rails.Count}");

        // ── Validation summary ─────────────────────────────────────────────────
        if (world.StageHashes.TryGetValue("ValidationPass", out ulong vhash))
        {
            int violations = (int)(vhash / 1000);
            int warnings   = (int)(vhash % 1000);
            Console.WriteLine();
            Console.WriteLine("═══════════════════════════════════════════════════════");
            Console.WriteLine(" VALIDATION");
            Console.WriteLine("═══════════════════════════════════════════════════════");
            Console.WriteLine($"  Violations : {violations}");
            Console.WriteLine($"  Warnings   : {warnings}");
        }

        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;
    }
}
