@namespace SufiChain.SufiBlazor.Components.Builder
@typeparam TItem

<div class="sb-sortable-list @(Orientation == SbSortableOrientation.Horizontal ? "sb-sortable-list--horizontal" : "") @Class">
    @foreach (var (item, index) in Items.Select((item, i) => (item, i)))
    {
        var isDropTarget = _dropIndex == index;
        <div class="sb-sortable-list__item @(_dragIndex == index ? "sb-sortable-list__item--dragging" : "") @(isDropTarget ? "sb-sortable-list__item--drop-target" : "")"
             draggable="@(!Disabled)"
             @ondragstart="() => OnDragStart(index)"
             @ondragenter="() => OnDragEnter(index)"
             @ondragover:preventDefault="true"
             @ondrop="OnDrop"
             @ondragend="OnDragEnd">
            
            @if (ShowHandles)
            {
                <div class="sb-sortable-list__handle">
                    <SbDragHandle Disabled="@Disabled" />
                </div>
            }
            
            <div class="sb-sortable-list__content">
                @ItemTemplate(item)
            </div>
            
            @if (Removable)
            {
                <button type="button" 
                        class="sb-sortable-list__remove"
                        @onclick="() => RemoveItem(index)"
                        aria-label="Remove">
                    ×
                </button>
            }
        </div>
    }
    
    @if (!Items.Any() && EmptyTemplate != null)
    {
        <div class="sb-sortable-list__empty">
            @EmptyTemplate
        </div>
    }
</div>

@code {
    private int _dragIndex = -1;
    private int _dropIndex = -1;
    
    /// <summary>
    /// List items.
    /// </summary>
    [Parameter]
    public List<TItem> Items { get; set; } = new();
    
    /// <summary>
    /// Callback when items are reordered.
    /// </summary>
    [Parameter]
    public EventCallback<List<TItem>> ItemsChanged { get; set; }
    
    /// <summary>
    /// Item template.
    /// </summary>
    [Parameter]
    public RenderFragment<TItem> ItemTemplate { get; set; } = default!;
    
    /// <summary>
    /// Empty state template.
    /// </summary>
    [Parameter]
    public RenderFragment? EmptyTemplate { get; set; }
    
    /// <summary>
    /// Whether to show drag handles.
    /// </summary>
    [Parameter]
    public bool ShowHandles { get; set; } = true;
    
    /// <summary>
    /// Whether items can be removed.
    /// </summary>
    [Parameter]
    public bool Removable { get; set; }
    
    /// <summary>
    /// List orientation.
    /// </summary>
    [Parameter]
    public SbSortableOrientation Orientation { get; set; } = SbSortableOrientation.Vertical;
    
    /// <summary>
    /// Whether the list is disabled.
    /// </summary>
    [Parameter]
    public bool Disabled { get; set; }
    
    /// <summary>
    /// Callback when item is removed.
    /// </summary>
    [Parameter]
    public EventCallback<TItem> OnItemRemoved { get; set; }
    
    /// <summary>
    /// Additional CSS classes.
    /// </summary>
    [Parameter]
    public string? Class { get; set; }
    
    private void OnDragStart(int index)
    {
        if (Disabled) return;
        _dragIndex = index;
    }
    
    private void OnDragEnter(int index)
    {
        if (_dragIndex < 0) return;
        _dropIndex = index;
    }
    
    private async Task OnDrop()
    {
        if (_dragIndex < 0 || _dropIndex < 0 || _dragIndex == _dropIndex)
        {
            ResetDrag();
            return;
        }
        
        var item = Items[_dragIndex];
        Items.RemoveAt(_dragIndex);
        
        var insertIndex = _dropIndex > _dragIndex ? _dropIndex - 1 : _dropIndex;
        Items.Insert(insertIndex, item);
        
        await ItemsChanged.InvokeAsync(Items);
        ResetDrag();
    }
    
    private void OnDragEnd()
    {
        ResetDrag();
    }
    
    private void ResetDrag()
    {
        _dragIndex = -1;
        _dropIndex = -1;
    }
    
    private async Task RemoveItem(int index)
    {
        var item = Items[index];
        Items.RemoveAt(index);
        await ItemsChanged.InvokeAsync(Items);
        await OnItemRemoved.InvokeAsync(item);
    }
}

public enum SbSortableOrientation
{
    Vertical,
    Horizontal
}
