@namespace Lumeo
@implements IAsyncDisposable

@if (Context.IsOpen)
{
    <div id="@_contentId" class="@CssClass" @onmouseenter="() => Context.RequestOpen.InvokeAsync()" @onmouseleave="() => Context.RequestClose.InvokeAsync()" @attributes="AdditionalAttributes">
        @ChildContent
        @if (ShowArrow)
        {
            <div class="@ArrowClasses"></div>
        }
    </div>
}

@inject ComponentInteropService Interop

@code {
    [CascadingParameter] public HoverCard.HoverCardContext Context { get; set; } = default!;
    [Parameter] public RenderFragment? ChildContent { get; set; }
    [Parameter] public HoverCardAlign Align { get; set; } = HoverCardAlign.Center;
    [Parameter] public HoverCardSide Side { get; set; } = HoverCardSide.Bottom;
    [Parameter] public bool ShowArrow { get; set; }
    [Parameter] public string? Class { get; set; }
    [Parameter(CaptureUnmatchedValues = true)] public Dictionary<string, object>? AdditionalAttributes { get; set; }

    private readonly string _contentId = $"hovercard-content-{Guid.NewGuid():N}";
    private bool _positioned;

    private string CssClass => string.Join(" ", new[] { "fixed z-50 w-64 rounded-md border border-border/60 bg-popover p-4 text-popover-foreground shadow-lg outline-none", ShowArrow ? "overflow-visible" : "", "animate-fade-in", Class }.Where(s => !string.IsNullOrWhiteSpace(s)));

    private string ArrowClasses => Side switch
    {
        HoverCardSide.Top => "absolute left-1/2 top-full -translate-x-1/2 -translate-y-1/2 rotate-45 h-2.5 w-2.5 bg-popover border-b border-r border-border/60",
        HoverCardSide.Bottom => "absolute left-1/2 bottom-full -translate-x-1/2 translate-y-1/2 rotate-45 h-2.5 w-2.5 bg-popover border-t border-l border-border/60",
        _ => "absolute left-1/2 bottom-full -translate-x-1/2 translate-y-1/2 rotate-45 h-2.5 w-2.5 bg-popover border-t border-l border-border/60"
    };

    private string AlignStr => Align switch
    {
        HoverCardAlign.Start => "start",
        HoverCardAlign.Center => "center",
        HoverCardAlign.End => "end",
        _ => "center"
    };

    private string SideStr => Side switch
    {
        HoverCardSide.Top => "top",
        HoverCardSide.Bottom => "bottom",
        _ => "bottom"
    };

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (Context.IsOpen && !_positioned)
        {
            await Interop.PositionFixed(_contentId, Context.WrapperId, AlignStr, false, SideStr);
            _positioned = true;
        }
        else if (!Context.IsOpen && _positioned)
        {
            try { await Interop.UnpositionFixed(_contentId); } catch (JSDisconnectedException) { }
            _positioned = false;
        }
    }

    public async ValueTask DisposeAsync()
    {
        if (_positioned)
        {
            try { await Interop.UnpositionFixed(_contentId); } catch (JSDisconnectedException) { }
            _positioned = false;
        }
    }

    public enum HoverCardAlign { Start, Center, End }
    public enum HoverCardSide { Top, Bottom }
}
