namespace Theriapolis.Core.World.Generation.Stages;

/// <summary>
/// Stage 18 — TradeRouteGen
/// Supply/demand matching overlay. Adjusts WealthLevel on settlements that sit on
/// high-traffic trade paths. No new polylines — uses existing road/rail network.
/// </summary>
public sealed class TradeRouteGenStage : IWorldGenStage
{
    public string Name => "TradeRouteGen";

    public void Run(WorldGenContext ctx)
    {
        var world = ctx.World;

        // Build adjacency list from road polylines (settlement endpoints)
        var adj = new Dictionary<int, List<(int toId, float cost)>>();
        foreach (var s in world.Settlements.Where(s => !s.IsPoi))
            adj[s.Id] = new List<(int, float)>();

        foreach (var road in world.Roads)
        {
            if (road.FromSettlementId < 0 || road.ToSettlementId < 0) continue;
            float routeLen = road.Points.Count > 0 ? road.Points.Count * 0.1f : 1f;
            if (adj.TryGetValue(road.FromSettlementId, out var la)) la.Add((road.ToSettlementId, routeLen));
            if (adj.TryGetValue(road.ToSettlementId,   out var lb)) lb.Add((road.FromSettlementId, routeLen));
        }
        foreach (var rail in world.Rails)
        {
            if (rail.FromSettlementId < 0 || rail.ToSettlementId < 0) continue;
            float routeLen = rail.Points.Count > 0 ? rail.Points.Count * 0.05f : 1f; // rail cheaper
            if (adj.TryGetValue(rail.FromSettlementId, out var la)) la.Add((rail.ToSettlementId, routeLen));
            if (adj.TryGetValue(rail.ToSettlementId,   out var lb)) lb.Add((rail.FromSettlementId, routeLen));
        }

        // Simple trade flow: for each pair of settlements with complementary economies,
        // compute trade score and distribute wealth bonus along the path
        var settleById = world.Settlements.Where(s => !s.IsPoi).ToDictionary(s => s.Id);
        var tradeScore = new Dictionary<int, float>();
        foreach (var s in settleById.Values) tradeScore[s.Id] = 0f;

        foreach (var producer in settleById.Values)
        foreach (var consumer in settleById.Values)
        {
            if (producer.Id == consumer.Id) continue;
            if (producer.Economy == consumer.Economy) continue; // same economy = no trade

            float supply = ProducerStrength(producer);
            float demand = ConsumerNeed(consumer, producer.Economy);
            if (supply <= 0 || demand <= 0) continue;

            // Approximate transport cost as Euclidean distance (no full Dijkstra for all pairs)
            float dist = MathF.Sqrt(
                (producer.TileX - consumer.TileX) * (float)(producer.TileX - consumer.TileX) +
                (producer.TileY - consumer.TileY) * (float)(producer.TileY - consumer.TileY));
            if (dist > 200) continue; // too far to trade efficiently

            float score = supply * demand / (1f + dist * 0.02f);
            tradeScore[producer.Id] += score;
            tradeScore[consumer.Id] += score;
        }

        // Normalize and apply wealth bonus
        float maxScore = tradeScore.Values.DefaultIfEmpty(1f).Max();
        if (maxScore < 1e-6f) return;

        foreach (var s in settleById.Values)
        {
            float bonus = tradeScore[s.Id] / maxScore * 0.3f;
            s.WealthLevel = Math.Clamp(s.WealthLevel + bonus, 0f, 1f);
        }

        ctx.LogMessage("[TradeRouteGen] Trade routes computed and wealth adjusted.");
    }

    private static float ProducerStrength(Settlement s) => s.Economy switch
    {
        SettlementEconomy.Farming      => 0.8f,
        SettlementEconomy.Mining       => 0.9f,
        SettlementEconomy.Fishing      => 0.7f,
        SettlementEconomy.Manufacturing=> 1.0f,
        SettlementEconomy.Trade        => 0.5f,
        SettlementEconomy.Military     => 0.3f,
        _                              => 0.5f,
    };

    private static float ConsumerNeed(Settlement consumer, SettlementEconomy producerEcon)
    {
        // Settlements need what they don't produce
        if (consumer.Economy == producerEcon) return 0f;
        return consumer.Economy switch
        {
            SettlementEconomy.Manufacturing => producerEcon is SettlementEconomy.Mining or SettlementEconomy.Farming ? 1.0f : 0.3f,
            SettlementEconomy.Military      => producerEcon is SettlementEconomy.Farming or SettlementEconomy.Manufacturing ? 0.8f : 0.2f,
            SettlementEconomy.Trade         => 0.6f,
            _                              => 0.4f,
        };
    }
}
