@inject IEntityDialogService entityDialogService
@inject NavigationManager NavigationManager

<div class="techTreeContainer" @ref="containerRef">
    <svg class="techTreeSvg" width="@svgWidth" height="@svgHeight">
        <!-- Edges -->
        @foreach (var edge in Graph.Edges)
        {
            var source = Graph.Nodes.FirstOrDefault(n => n.Id == edge.SourceId);
            var target = Graph.Nodes.FirstOrDefault(n => n.Id == edge.TargetId);
            if (source != null && target != null)
            {
                var color = EdgeColor(edge.EdgeType);
                var strokeWidth = edge.EdgeType == TechTreeEdgeType.Produces ? "2.5" : "1.5";
                var strokeDash = edge.EdgeType == TechTreeEdgeType.RequiresProduction || edge.EdgeType == TechTreeEdgeType.RequiresResearch ? "6,3" : "";
                strokeDash = edge.EdgeType == TechTreeEdgeType.Morph ? "2,2" : strokeDash;

                <line x1="@(source.X + nodeWidth / 2)" y1="@(source.Y + nodeHeight / 2)"
                      x2="@(target.X + nodeWidth / 2)" y2="@(target.Y + nodeHeight / 2)"
                      stroke="@color" stroke-width="@strokeWidth"
                      stroke-dasharray="@strokeDash"
                      marker-end="url(#arrowhead-@(edge.EdgeType))"/>
            }
        }

        <!-- Arrowhead markers -->
        <defs>
            @foreach (var edgeType in Graph.Edges.Select(e => e.EdgeType).Distinct())
            {
                <marker id="arrowhead-@edgeType" markerWidth="10" markerHeight="7" refX="10" refY="3.5" orient="auto">
                    <polygon points="0 0, 10 3.5, 0 7" fill="@EdgeColor(edgeType)"/>
                </marker>
            }
        </defs>

        <!-- Nodes -->
        @foreach (var node in Graph.Nodes)
        {
            var color = NodeColor(node.Descriptive);
            var isHighlighted = HighlightEntityId == node.Id;

            <g class="techTreeNode" @onclick="() => OnNodeClick(node.Id)">
                <rect x="@node.X" y="@node.Y" width="@nodeWidth" height="@nodeHeight" rx="6"
                      fill="var(--paper)" stroke="@color" stroke-width="@(isHighlighted ? 3 : 1.5)"
                      class="@(isHighlighted ? "highlighted" : "")"/>
                <text x="@(node.X + nodeWidth / 2)" y="@(node.Y + nodeHeight / 2)"
                      text-anchor="middle" dominant-baseline="central"
                      fill="white" font-size="12" font-weight="600">
                    @TruncateText(node.Name, 20)
                </text>
                <title>@node.Name (@node.EntityType)</title>
            </g>
        }
    </svg>
</div>

<style>
    .techTreeContainer {
        width: 100%;
        overflow: auto;
        border: 2px solid var(--paper-border);
        border-radius: 8px;
        background-color: var(--background);
    }

    .techTreeSvg {
        display: block;
    }

    .techTreeNode {
        cursor: pointer;
    }

    .techTreeNode rect {
        transition: stroke-width 0.15s;
    }

    .techTreeNode rect.highlighted {
        filter: drop-shadow(0 0 6px rgba(255, 255, 255, 0.5));
    }

    .techTreeNode:hover rect {
        stroke-width: 3;
    }
</style>

@code {

    [Parameter] public TechTreeGraphModel Graph { get; set; } = new();

    [Parameter] public string? HighlightEntityId { get; set; }

    [Parameter] public EventCallback<string> OnEntitySelected { get; set; }

    private ElementReference containerRef;
    private const float nodeWidth = 140;
    private const float nodeHeight = 36;
    private const float horizontalSpacing = 60;
    private const float verticalSpacing = 30;
    private const float topPadding = 40;
    private const float leftPadding = 40;

    private float svgWidth = 800;
    private float svgHeight = 600;

    protected override void OnParametersSet()
    {
        ComputeLayout();
    }

    void ComputeLayout()
    {
        if (Graph.Nodes.Count == 0) return;

        var layers = Graph.Nodes.GroupBy(n => n.Layer)
            .OrderBy(g => g.Key)
            .ToList();

        // Simple layered layout: left to right (layers are columns)
        for (var layerIdx = 0; layerIdx < layers.Count; layerIdx++)
        {
            var layerNodes = layers.ElementAt(layerIdx).OrderBy(n => n.Name).ToList();
            var layerHeight = layerNodes.Count * (nodeHeight + verticalSpacing) - verticalSpacing;

            for (var nodeIdx = 0; nodeIdx < layerNodes.Count; nodeIdx++)
            {
                var node = layerNodes[nodeIdx];
                node.X = leftPadding + layerIdx * (nodeWidth + horizontalSpacing);
                node.Y = topPadding + nodeIdx * (nodeHeight + verticalSpacing);
            }
        }

        svgWidth = layers.Count * (nodeWidth + horizontalSpacing) + leftPadding + 100;
        svgHeight = layers.Max(g => g.Count()) * (nodeHeight + verticalSpacing) + topPadding + 80;

        if (svgWidth < 800) svgWidth = 800;
        if (svgHeight < 400) svgHeight = 400;
    }

    void OnNodeClick(string entityId)
    {
        entityDialogService.AddDialog(entityId);
        OnEntitySelected.InvokeAsync(entityId);
    }

    string NodeColor(string descriptive)
    {
        return descriptive.ToLowerInvariant() switch
        {
            "frontliner" => "#ff6b6b",
            "skirmisher" => "#ffa502",
            "support" => "#2ed573",
            "generalist" => "#1e90ff",
            "worker" => "#ffd43b",
            "stronghold" => "#ff4757",
            "upgrade" => "#a55eea",
            "technology" => "#a55eea",
            _ => "#8fc5ff"
        };
    }

    string EdgeColor(string edgeType)
    {
        return edgeType switch
        {
            "Produces" => "#2ed573",
            "RequiresProduction" => "#ffa502",
            "RequiresResearch" => "#a55eea",
            "Morph" => "#ff6b6b",
            "Upgrades" => "#1e90ff",
            _ => "#666"
        };
    }

    string TruncateText(string text, int maxLength)
    {
        return text.Length <= maxLength ? text : text.Substring(0, maxLength - 3) + "...";
    }

}
