@using MudBlazor
@using System.Collections
@using System.Reflection

<MudDialog>
    <DialogContent>
        <div class="list-editor-layout">
            <div class="list-editor-list">
                <MudList T="int" Dense="true" @bind-SelectedValue="_selectedIndex">
                    @for (int i = 0; i < _items.Count; i++)
                    {
                        var idx = i;
                        <MudListItem T="int" Value="@idx"
                                     Text="@(_items[idx]?.ToString() ?? "(null)")" />
                    }
                </MudList>
            </div>
            <div class="list-editor-buttons">
                <MudButton Variant="Variant.Outlined" Color="Color.Primary" OnClick="Add" FullWidth="true">Add</MudButton>
                <MudButton Variant="Variant.Outlined" Color="Color.Primary" OnClick="Edit" FullWidth="true"
                           Disabled="@(_selectedIndex < 0)">Edit</MudButton>
                <MudButton Variant="Variant.Outlined" Color="Color.Primary" OnClick="Remove" FullWidth="true"
                           Disabled="@(_selectedIndex < 0)">Remove</MudButton>
            </div>
        </div>
    </DialogContent>
    <DialogActions>
        <MudButton OnClick="Cancel">Cancel</MudButton>
        <MudButton Color="Color.Primary" OnClick="Ok">OK</MudButton>
    </DialogActions>
</MudDialog>

@code {
    [CascadingParameter] private IMudDialogInstance MudDialog { get; set; } = null!;
    [Parameter] public Type ElementType { get; set; } = null!;
    [Parameter] public IList? InitialList { get; set; }

    [Microsoft.AspNetCore.Components.Inject] private IDialogService DialogService { get; set; } = null!;

    private List<object?> _items = new();
    private int _selectedIndex = -1;

    protected override void OnParametersSet()
    {
        _items.Clear();
        if (InitialList != null)
        {
            foreach (var item in InitialList)
                _items.Add(CloneObject(item));
        }
    }

    private async Task Add()
    {
        var defaultValue = GetDefaultValue(ElementType);
        var result = await EditItem(defaultValue);
        if (result != null)
        {
            _items.Add(result);
            _selectedIndex = _items.Count - 1;
        }
    }

    private async Task Edit()
    {
        if (_selectedIndex < 0 || _selectedIndex >= _items.Count) return;
        var result = await EditItem(_items[_selectedIndex]);
        if (result != null)
        {
            _items[_selectedIndex] = result;
        }
    }

    private void Remove()
    {
        if (_selectedIndex < 0 || _selectedIndex >= _items.Count) return;
        _items.RemoveAt(_selectedIndex);
        if (_items.Count > 0)
            _selectedIndex = Math.Min(_selectedIndex, _items.Count - 1);
        else
            _selectedIndex = -1;
    }

    private async Task<object?> EditItem(object? value)
    {
        if (ElementType.IsValueType || ElementType == typeof(string) || ElementType.IsEnum)
        {
            // Simple type: inline edit via ItemEditorDialog
            var parameters = new DialogParameters<ItemEditorDialog>
            {
                { x => x.ItemType, ElementType },
                { x => x.InitialValue, value }
            };
            var dialog = await DialogService.ShowAsync<ItemEditorDialog>($"Edit {ElementType.Name}", parameters);
            var result = await dialog.Result;
            if (result != null && !result.Canceled)
                return result.Data;
            return null;
        }
        else
        {
            // Complex type: edit properties
            var parameters = new DialogParameters<ItemEditorDialog>
            {
                { x => x.ItemType, ElementType },
                { x => x.InitialValue, CloneObject(value) }
            };
            var dialog = await DialogService.ShowAsync<ItemEditorDialog>($"Edit {ElementType.Name}", parameters);
            var result = await dialog.Result;
            if (result != null && !result.Canceled)
                return result.Data;
            return null;
        }
    }

    private void Ok()
    {
        var listType = typeof(List<>).MakeGenericType(ElementType);
        var resultList = (IList)Activator.CreateInstance(listType)!;
        foreach (var item in _items)
            resultList.Add(item);
        MudDialog.Close(DialogResult.Ok(resultList));
    }

    private void Cancel() => MudDialog.Cancel();

    private object? GetDefaultValue(Type type)
    {
        if (type.IsValueType) return Activator.CreateInstance(type);
        if (type == typeof(string)) return "";
        try { return Activator.CreateInstance(type); }
        catch { return null; }
    }

    private object? CloneObject(object? obj)
    {
        if (obj == null) return null;
        var type = obj.GetType();
        if (type.IsValueType || type == typeof(string)) return obj;
        try
        {
            var clone = Activator.CreateInstance(type);
            foreach (var prop in type.GetProperties(BindingFlags.Public | BindingFlags.Instance))
            {
                if (prop.CanRead && prop.CanWrite)
                    prop.SetValue(clone, prop.GetValue(obj));
            }
            return clone;
        }
        catch { return obj; }
    }
}
