@using ZB.MOM.WW.ScadaBridge.CentralUI.Components.Shared
@using ZB.MOM.WW.ScadaBridge.CentralUI.Services
@using ZB.MOM.WW.ScadaBridge.Commons.Types.Audit
@using ZB.MOM.WW.ScadaBridge.Commons.Types.Enums
@inject IAuditLogQueryService QueryService

<div data-test="audit-results-grid">
    @if (_error is not null)
    {
        <div class="alert alert-danger small mb-2">@_error</div>
    }

    <div class="table-responsive">
        <table class="table table-sm table-hover align-middle" @ref="_tableRef">
            <thead class="table-light">
                <tr>
                    @foreach (var col in OrderedColumns())
                    {
                        // @key keeps Blazor reusing one DOM node per column across
                        // re-renders (reorder/resize), so audit-grid.js binds drag
                        // listeners exactly once per <th> and never leaks them onto
                        // discarded nodes — the __auditGridCellBound guard relies on
                        // this node stability to be fully sound.
                        <th class="audit-grid-th"
                            @key="col.Key"
                            data-test="col-header-@col.Key"
                            data-col-key="@col.Key"
                            style="@ColumnWidthStyle(col.Key)">
                            @col.Label
                            <span class="audit-grid-resize-handle"
                                  data-test="col-resize-@col.Key"
                                  aria-hidden="true"></span>
                        </th>
                    }
                </tr>
            </thead>
            <tbody>
                @if (_rows.Count == 0)
                {
                    <tr>
                        <td colspan="@OrderedColumns().Count" class="text-muted small text-center py-4">
                            @if (_loading)
                            {
                                <span>Loading…</span>
                            }
                            else
                            {
                                <span>No audit events match the current filter.</span>
                            }
                        </td>
                    </tr>
                }
                else
                {
                    @foreach (var row in _rows)
                    {
                        <tr @key="row.EventId"
                            data-test="grid-row-@row.EventId"
                            class="audit-row"
                            style="cursor: pointer;"
                            @onclick="() => HandleRowClick(row)">
                            @foreach (var col in OrderedColumns())
                            {
                                <td class="audit-grid-td" style="@ColumnWidthStyle(col.Key)">
                                    @RenderCell(col.Key, row)
                                </td>
                            }
                        </tr>
                    }
                }
            </tbody>
        </table>
    </div>

    <div class="d-flex justify-content-between align-items-center">
        <span class="text-muted small">Page @_pageNumber · @_rows.Count rows</span>
        @* CentralUI-032: keyset paging is naturally forward-only, but the
           in-component _cursorStack lets the user step back through previous
           pages by replaying the prior cursor. The Previous button is gated
           on the stack having at least one prior cursor — i.e. we are not on
           the first page. *@
        <div class="btn-group">
            <button class="btn btn-outline-secondary btn-sm"
                    data-test="grid-prev-page"
                    disabled="@(_loading || !CanGoBack)"
                    @onclick="PrevPage">Previous page</button>
            <button class="btn btn-outline-secondary btn-sm"
                    data-test="grid-next-page"
                    disabled="@(_loading || _rows.Count < _pageSize)"
                    @onclick="NextPage">Next page</button>
        </div>
    </div>
</div>

@code {
    // Compact display for Guid id columns: the first 8 hex digits, mirroring
    // the drilldown drawer's ShortEventId presentation. The full value is kept
    // in the cell's title attribute so it stays copy-paste accessible.
    private static string ShortGuid(Guid value)
    {
        var n = value.ToString("N");
        return n.Length >= 8 ? n[..8] : n;
    }

    private RenderFragment RenderCell(string key, AuditEventView row) => __builder =>
    {
        switch (key)
        {
            case "OccurredAtUtc":
                var occurredOffset = new DateTimeOffset(DateTime.SpecifyKind(row.OccurredAtUtc, DateTimeKind.Utc));
                <span title="@row.OccurredAtUtc.ToString("u")">
                    <TimestampDisplay Value="occurredOffset" Format="yyyy-MM-dd HH:mm:ss" />
                </span>
                break;
            case "Site":
                <span class="small">@(row.SourceSiteId ?? "—")</span>
                break;
            case "Node":
                <span class="small">@(row.SourceNode ?? "—")</span>
                break;
            case "Channel":
                <span class="small">@row.Channel</span>
                break;
            case "Kind":
                <span class="small">@row.Kind</span>
                break;
            case "Status":
                <span data-test="status-badge-@row.EventId" class="badge @StatusBadgeClass(row.Status)">@row.Status</span>
                break;
            case "Target":
                <span class="small">@(row.Target ?? "—")</span>
                break;
            case "Actor":
                <span class="small">@(row.Actor ?? "—")</span>
                break;
            case "ExecutionId":
                @if (row.ExecutionId is { } executionId)
                {
                    <span class="small font-monospace"
                          data-test="execution-id-@row.EventId"
                          title="@executionId">@ShortGuid(executionId)</span>
                }
                else
                {
                    <span class="small text-muted">—</span>
                }
                break;
            case "ParentExecutionId":
                @if (row.ParentExecutionId is { } parentExecutionId)
                {
                    <span class="small font-monospace"
                          data-test="parent-execution-id-@row.EventId"
                          title="@parentExecutionId">@ShortGuid(parentExecutionId)</span>
                }
                else
                {
                    <span class="small text-muted">—</span>
                }
                break;
            case "DurationMs":
                <span class="small font-monospace">@(row.DurationMs?.ToString() ?? "—")</span>
                break;
            case "HttpStatus":
                <span class="small font-monospace">@(row.HttpStatus?.ToString() ?? "—")</span>
                break;
            case "ErrorMessage":
                <span class="small text-danger" title="@row.ErrorMessage">@TruncateError(row.ErrorMessage)</span>
                break;
        }
    };
}
