@inherits BandGridBase<CatalogReadDto>
@inject ICatalogApiClient Api

@if (!string.IsNullOrWhiteSpace(errorMessage))
{
    <div class="alert alert-danger" role="alert">@errorMessage</div>
}
else if (!string.IsNullOrWhiteSpace(infoMessage))
{
    <div class="alert alert-success" role="alert">@infoMessage</div>
}

@if (!hasLoaded || isLoading)
{
    <div class="loading-container">
        <div class="spinner-border text-primary" role="status">
            <span class="visually-hidden">Lade...</span>
        </div>
    </div>
}
else if (items.Count == 0)
{
    <p>Keine Einträge vorhanden.</p>
}
else
{
    <BandEditor Bands="@bandLayout.Bands"
                BandOptions="@bandOptions"
                Columns="@ColumnDefinitions"
                GetColumnBand="GetColumnBand"
                CanSave="@CanSaveBandLayout"
                OnAddBand="AddBand"
                OnSaveLayout="SaveLayoutWithFeedbackAsync"
                OnResetLayout="ResetLayoutWithFeedbackAsync"
                OnRemoveBand="RemoveBand"
                OnBandCaptionChanged="@(args => UpdateBandCaption(args.Band, args.Value))"
                OnColumnBandChanged="@(args => UpdateColumnBand(args.FieldName, args.BandId))" />

    <div class="grid-section">
        <DxGrid Data="@items"
                ColumnChooserButtonDisplayMode="GridColumnChooserButtonDisplayMode.Always"
                TItem="CatalogReadDto"
                KeyFieldName="@nameof(CatalogReadDto.Guid)"
                SizeMode="@_sizeMode"
                ShowGroupPanel="true"
                ShowGroupedColumns="true"
                AllowGroup="true"
                FilterMenuButtonDisplayMode="GridFilterMenuButtonDisplayMode.Always"
                AllowColumnResize="true"
                ColumnResizeMode="GridColumnResizeMode.ColumnsContainer"
                AllowColumnReorder="true"
                PageSize="10"
                CssClass="mb-4 catalog-grid"
                EditMode="GridEditMode.PopupEditForm"
                PopupEditFormCssClass="catalog-edit-popup"
                PopupEditFormHeaderText="@popupHeaderText"
                CustomizeEditModel="OnCustomizeEditModel"
                EditModelSaving="OnEditModelSaving"
                DataItemDeleting="OnDataItemDeleting"
                FocusedRowEnabled="true"
                @bind-FocusedRowKey="focusedRowKey"
                RowClick="@(args => _focusedVisibleIndex = args.VisibleIndex)"
                @ref="gridRef">
            <ToolbarTemplate>
                <DxToolbar>
                    <DxToolbarItem Alignment="ToolbarItemAlignment.Left">
                        <Template Context="_">
                            <DxButton IconCssClass="bi bi-plus-lg"
                                      RenderStyle="ButtonRenderStyle.Secondary"
                                      RenderStyleMode="ButtonRenderStyleMode.Text"
                                      Click="@(() => gridRef!.StartEditNewRowAsync())" />
                        </Template>
                    </DxToolbarItem>
                    <DxToolbarItem Alignment="ToolbarItemAlignment.Left">
                        <Template Context="_">
                            <DxButton IconCssClass="bi bi-pencil"
                                      RenderStyle="ButtonRenderStyle.Secondary"
                                      RenderStyleMode="ButtonRenderStyleMode.Text"
                                      Click="EditFocusedRow" />
                        </Template>
                    </DxToolbarItem>
                    <DxToolbarItem Alignment="ToolbarItemAlignment.Left">
                        <Template Context="_">
                            <DxButton IconCssClass="bi bi-trash"
                                      RenderStyle="ButtonRenderStyle.Secondary"
                                      RenderStyleMode="ButtonRenderStyleMode.Text"
                                      Click="DeleteFocusedRow" />
                        </Template>
                    </DxToolbarItem>
                    <DxToolbarItem Alignment="ToolbarItemAlignment.Right">
                        <Template Context="_">
                            <DxButton Text="Spalten"
                                      RenderStyle="ButtonRenderStyle.Secondary"
                                      RenderStyleMode="ButtonRenderStyleMode.Text"
                                      Click="@(() => gridRef!.ShowColumnChooser())" />
                        </Template>
                    </DxToolbarItem>
                    <DxToolbarItem Alignment="ToolbarItemAlignment.Right">
                        <Template Context="_">
                            <DxDropDownButton Text="@FormatSizeText(_sizeMode)"
                                              RenderStyle="ButtonRenderStyle.Secondary"
                                              RenderStyleMode="ButtonRenderStyleMode.Text"
                                              ItemClick="OnSizeChange">
                                <Items>
                                    @foreach (var size in _sizeModes)
                                    {
                                        <DxDropDownButtonItem Text="@FormatSizeText(size)" Id="@size.ToString()" />
                                    }
                                </Items>
                            </DxDropDownButton>
                        </Template>
                    </DxToolbarItem>
                </DxToolbar>
            </ToolbarTemplate>
            <Columns>
                @RenderColumns()
            </Columns>
            <EditFormTemplate Context="editFormContext">
                @{
                    SetEditContext(editFormContext.EditContext); var editModel = (CatalogEditModel)editFormContext.EditModel; SetPopupHeaderText(editModel.IsNew);
                }
                <DxFormLayout ColCount="2">
                    <DxFormLayoutItem Caption="Titel">
                        <DxTextBox @bind-Text="editModel.CatTitle" Width="100%" />
                    </DxFormLayoutItem>
                    <DxFormLayoutItem Caption="Kennung">
                        <DxTextBox @bind-Text="editModel.CatString" Width="100%" />
                    </DxFormLayoutItem>
                    @if (!editModel.IsNew)
                    {
                        <DxFormLayoutItem Caption="Update-Prozedur">
                            <DxComboBox Data="@procedureOptions"
                                        TData="ProcedureOption"
                                        TValue="int"
                                        TextFieldName="Text"
                                        ValueFieldName="Value"
                                        @bind-Value="editModel.UpdateProcedure"
                                        Width="100%" />
                        </DxFormLayoutItem>
                    }
                    <DxFormLayoutItem ColSpanMd="12">
                        <ValidationSummary />
                    </DxFormLayoutItem>
                </DxFormLayout>
            </EditFormTemplate>
        </DxGrid>
    </div>
}

@code {
    private List<CatalogReadDto> items = new();
    private int? focusedRowKey;

    protected override string LayoutKey => "CatalogsGrid";
    protected override bool ShowCommandColumn => false;

    protected override List<ColumnDefinition> ColumnDefinitions { get; } = new()
{
    new() { FieldName = nameof(CatalogReadDto.Guid),       Caption = "Id",          Width = "140px", FilterType = ColumnFilterType.Text },
    new() { FieldName = nameof(CatalogReadDto.CatTitle),   Caption = "Titel",                        FilterType = ColumnFilterType.Text },
    new() { FieldName = nameof(CatalogReadDto.CatString),  Caption = "String",                       FilterType = ColumnFilterType.Text },
    new() { FieldName = nameof(CatalogReadDto.AddedWho),   Caption = "Angelegt von", ReadOnly = true, FilterType = ColumnFilterType.Text },
    new() { FieldName = nameof(CatalogReadDto.AddedWhen),  Caption = "Angelegt am",  ReadOnly = true, FilterType = ColumnFilterType.Date },
    new() { FieldName = nameof(CatalogReadDto.ChangedWho), Caption = "Geändert von", ReadOnly = true, FilterType = ColumnFilterType.Text },
    new() { FieldName = nameof(CatalogReadDto.ChangedWhen),Caption = "Geändert am",  ReadOnly = true, FilterType = ColumnFilterType.Date }
};

    private readonly List<ProcedureOption> procedureOptions = new()
    {
        new() { Value = 0, Text = "PRTBMY_CATALOG_UPDATE" },
        new() { Value = 1, Text = "PRTBMY_CATALOG_SAVE" }
    };

    protected override async Task OnInitializedAsync()
    {
        await InitializeBandLayoutAsync();
        await LoadCatalogs();
    }

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        await ApplyGridLayoutAfterRenderAsync();
    }

    private async Task LoadCatalogs()
    {
        isLoading = true;
        errorMessage = null;
        try
        {
            items = await Api.GetAllAsync();
        }
        catch (Exception ex)
        {
            errorMessage = $"Kataloge konnten nicht geladen werden: {ex.Message}";
        }
        finally
        {
            isLoading = false;
            hasLoaded = true;
            StateHasChanged();
        }
    }

    protected override void OnEditFieldChanged(object? sender, FieldChangedEventArgs e)
    {
        if (validationMessageStore == null || editContext == null) return;

        if (e.FieldIdentifier.FieldName == nameof(CatalogEditModel.UpdateProcedure))
        {
            validationMessageStore.Clear();
            editContext.NotifyValidationStateChanged();
            return;
        }

        if (e.FieldIdentifier.FieldName == nameof(CatalogEditModel.CatTitle))
        {
            validationMessageStore.Clear(new FieldIdentifier(editContext.Model, nameof(CatalogEditModel.CatTitle)));
            editContext.NotifyValidationStateChanged();
        }
    }

    private void OnCustomizeEditModel(GridCustomizeEditModelEventArgs e)
    {
        popupHeaderText = e.IsNew ? "Neu" : "Edit";
        if (e.IsNew)
        {
            e.EditModel = new CatalogEditModel { IsNew = true };
            return;
        }

        var item = (CatalogReadDto)e.DataItem;
        e.EditModel = new CatalogEditModel
        {
            Guid = item.Guid,
            CatTitle = item.CatTitle,
            CatString = item.CatString,
            UpdateProcedure = 0,
            OriginalCatTitle = item.CatTitle,
            IsNew = false
        };
    }

    private async Task OnEditModelSaving(GridEditModelSavingEventArgs e)
    {
        errorMessage = null;
        infoMessage = null;
        validationMessageStore?.Clear();
        editContext?.NotifyValidationStateChanged();

        var editModel = (CatalogEditModel)e.EditModel;
        if (!ValidateEditModel(editModel, e.IsNew))
        {
            e.Cancel = true;
            return;
        }

        var dto = new CatalogWriteDto
        {
            CatTitle = editModel.CatTitle,
            CatString = editModel.CatString,
            UpdateProcedure = editModel.UpdateProcedure
        };

        try
        {
            if (e.IsNew)
            {
                var created = await Api.CreateAsync(dto);
                if (!created.Success || created.Value == null)
                {
                    if (!string.IsNullOrWhiteSpace(created.Error))
                        AddValidationError(editModel, nameof(CatalogEditModel.CatTitle), created.Error);
                    else
                        errorMessage = "Anlegen fehlgeschlagen.";
                    e.Cancel = true;
                    return;
                }
                infoMessage = "Katalog angelegt.";
                focusedRowKey = created.Value.Guid;
            }
            else
            {
                var updated = await Api.UpdateAsync(editModel.Guid, dto);
                if (!updated.Success)
                {
                    errorMessage = updated.Error ?? "Aktualisierung fehlgeschlagen.";
                    e.Cancel = true;
                    return;
                }
                infoMessage = "Katalog aktualisiert.";
                focusedRowKey = editModel.Guid;
            }

            await LoadCatalogs();
        }
        catch (Exception ex)
        {
            errorMessage = $"Fehler beim Speichern: {ex.Message}";
            e.Cancel = true;
        }
    }

    private void AddValidationError(CatalogEditModel editModel, string fieldName, string message)
    {
        if (editContext == null || validationMessageStore == null) return;
        validationMessageStore.Add(new FieldIdentifier(editModel, fieldName), message);
        editContext.NotifyValidationStateChanged();
    }

    private bool ValidateEditModel(CatalogEditModel editModel, bool isNew)
    {
        if (isNew) return true;
        if (editModel.UpdateProcedure == 0 &&
            !string.Equals(editModel.CatTitle, editModel.OriginalCatTitle, StringComparison.OrdinalIgnoreCase))
        {
            AddValidationError(editModel, nameof(CatalogEditModel.CatTitle), "Titel kann nicht geändert werden.");
            return false;
        }
        return true;
    }

    private async Task OnDataItemDeleting(GridDataItemDeletingEventArgs e)
    {
        errorMessage = null;
        infoMessage = null;
        var item = (CatalogReadDto)e.DataItem;
        try
        {
            var deleted = await Api.DeleteAsync(item.Guid);
            if (!deleted.Success)
            {
                errorMessage = deleted.Error ?? "Löschen fehlgeschlagen.";
                e.Cancel = true;
                return;
            }
            infoMessage = "Katalog gelöscht.";
            await LoadCatalogs();
        }
        catch (Exception ex)
        {
            errorMessage = $"Fehler beim Löschen: {ex.Message}";
            e.Cancel = true;
        }
    }

    private sealed class CatalogEditModel
    {
        public int Guid { get; set; }
        public string CatTitle { get; set; } = string.Empty;
        public string CatString { get; set; } = string.Empty;
        public int UpdateProcedure { get; set; }
        public string OriginalCatTitle { get; set; } = string.Empty;
        public bool IsNew { get; set; }
    }

    private sealed class ProcedureOption
    {
        public int Value { get; set; }
        public string Text { get; set; } = string.Empty;
    }
}