@page "/notifications/kpis"
@attribute [Authorize(Policy = ScadaLink.Security.AuthorizationPolicies.RequireDeployment)]
@using ScadaLink.Commons.Entities.Sites
@using ScadaLink.Commons.Interfaces.Repositories
@using ScadaLink.Commons.Messages.Notification
@using ScadaLink.Commons.Types.Notifications
@using ScadaLink.Communication
@inject CommunicationService CommunicationService
@inject ISiteRepository SiteRepository
@inject ILogger<NotificationKpis> Logger

<div class="container-fluid mt-3">
    <div class="d-flex justify-content-between align-items-center mb-3">
        <h4 class="mb-0">Notification KPIs</h4>
        <button class="btn btn-outline-secondary btn-sm" @onclick="RefreshAll" disabled="@_loading">
            @if (_loading) { <span class="spinner-border spinner-border-sm me-1" role="status"></span> }
            Refresh
        </button>
    </div>

    @* ── Global KPI tiles ── *@
    @if (_kpiError != null)
    {
        <div class="alert alert-warning py-2">KPIs unavailable: @_kpiError</div>
    }
    else
    {
        <div class="row g-3 mb-4">
            <div class="col-lg col-md-4 col-6">
                <div class="card h-100">
                    <div class="card-body text-center py-3">
                        <h3 class="mb-0">@_kpi.QueueDepth</h3>
                        <small class="text-muted">Queue Depth</small>
                    </div>
                </div>
            </div>
            <div class="col-lg col-md-4 col-6">
                <div class="card h-100 @(_kpi.StuckCount > 0 ? "border-warning" : "")">
                    <div class="card-body text-center py-3">
                        <h3 class="mb-0 @(_kpi.StuckCount > 0 ? "text-warning" : "")">@_kpi.StuckCount</h3>
                        <small class="text-muted">Stuck</small>
                    </div>
                </div>
            </div>
            <div class="col-lg col-md-4 col-6">
                <div class="card h-100 @(_kpi.ParkedCount > 0 ? "border-danger" : "")">
                    <div class="card-body text-center py-3">
                        <h3 class="mb-0 @(_kpi.ParkedCount > 0 ? "text-danger" : "")">@_kpi.ParkedCount</h3>
                        <small class="text-muted">Parked</small>
                    </div>
                </div>
            </div>
            <div class="col-lg col-md-4 col-6">
                <div class="card h-100">
                    <div class="card-body text-center py-3">
                        <h3 class="mb-0 text-success">@_kpi.DeliveredLastInterval</h3>
                        <small class="text-muted">Delivered (last interval)</small>
                    </div>
                </div>
            </div>
            <div class="col-lg col-md-4 col-6">
                <div class="card h-100">
                    <div class="card-body text-center py-3">
                        <h3 class="mb-0">@FormatAge(_kpi.OldestPendingAge)</h3>
                        <small class="text-muted">Oldest Pending Age</small>
                    </div>
                </div>
            </div>
        </div>
    }

    @* ── Per-site breakdown ── *@
    <h5 class="mb-2">Per-site breakdown</h5>
    @if (_perSiteError != null)
    {
        <div class="alert alert-warning py-2">Per-site KPIs unavailable: @_perSiteError</div>
    }
    else if (_perSite.Count == 0)
    {
        <div class="card">
            <div class="card-body text-center text-muted py-4">
                <div class="small">No per-site activity.</div>
            </div>
        </div>
    }
    else
    {
        <div class="table-responsive">
            <table class="table table-sm table-hover align-middle">
                <thead class="table-light">
                    <tr>
                        <th>Site</th>
                        <th class="text-end">Queue Depth</th>
                        <th class="text-end">Stuck</th>
                        <th class="text-end">Parked</th>
                        <th class="text-end">Delivered (last interval)</th>
                        <th class="text-end">Oldest Pending Age</th>
                    </tr>
                </thead>
                <tbody>
                    @foreach (var s in _perSite)
                    {
                        <tr @key="s.SourceSiteId" class="@(s.StuckCount > 0 ? "table-warning" : "")">
                            <td>@SiteName(s.SourceSiteId)</td>
                            <td class="text-end font-monospace">@s.QueueDepth</td>
                            <td class="text-end font-monospace @(s.StuckCount > 0 ? "text-warning" : "")">@s.StuckCount</td>
                            <td class="text-end font-monospace @(s.ParkedCount > 0 ? "text-danger" : "")">@s.ParkedCount</td>
                            <td class="text-end font-monospace text-success">@s.DeliveredLastInterval</td>
                            <td class="text-end font-monospace">@FormatAge(s.OldestPendingAge)</td>
                        </tr>
                    }
                </tbody>
            </table>
        </div>
    }
</div>

@code {
    private List<Site> _sites = new();

    private NotificationKpiResponse _kpi = new(string.Empty, true, null, 0, 0, 0, 0, null);
    private string? _kpiError;

    private IReadOnlyList<SiteNotificationKpiSnapshot> _perSite = Array.Empty<SiteNotificationKpiSnapshot>();
    private string? _perSiteError;

    private bool _loading;

    protected override async Task OnInitializedAsync()
    {
        try
        {
            _sites = (await SiteRepository.GetAllSitesAsync()).ToList();
        }
        catch (Exception ex)
        {
            // Non-fatal — the per-site table falls back to raw site identifiers.
            Logger.LogWarning(ex, "Failed to load sites for the KPI per-site breakdown.");
        }

        await RefreshAll();
    }

    private async Task RefreshAll()
    {
        _loading = true;
        // Race-free despite both tasks mutating component fields: Blazor Server runs
        // every continuation on the circuit's single-threaded synchronization context.
        await Task.WhenAll(LoadGlobalKpis(), LoadPerSiteKpis());
        _loading = false;
    }

    private async Task LoadGlobalKpis()
    {
        try
        {
            var response = await CommunicationService.GetNotificationKpisAsync(
                new NotificationKpiRequest(Guid.NewGuid().ToString("N")));
            if (response.Success)
            {
                _kpi = response;
                _kpiError = null;
            }
            else
            {
                _kpiError = response.ErrorMessage ?? "KPI query failed.";
            }
        }
        catch (Exception ex)
        {
            _kpiError = $"KPI query failed: {ex.Message}";
        }
    }

    private async Task LoadPerSiteKpis()
    {
        try
        {
            var response = await CommunicationService.GetPerSiteNotificationKpisAsync(
                new PerSiteNotificationKpiRequest(Guid.NewGuid().ToString("N")));
            if (response.Success)
            {
                _perSite = response.Sites;
                _perSiteError = null;
            }
            else
            {
                _perSiteError = response.ErrorMessage ?? "Per-site KPI query failed.";
            }
        }
        catch (Exception ex)
        {
            _perSiteError = $"Per-site KPI query failed: {ex.Message}";
        }
    }

    private string SiteName(string siteId) =>
        _sites.FirstOrDefault(s => s.SiteIdentifier == siteId)?.Name ?? siteId;

    private static string FormatAge(TimeSpan? age)
    {
        if (age == null) return "—";
        var t = age.Value;
        if (t.TotalSeconds < 60) return $"{(int)t.TotalSeconds}s";
        if (t.TotalMinutes < 60) return $"{(int)t.TotalMinutes}m";
        if (t.TotalHours < 24) return $"{(int)t.TotalHours}h";
        return $"{(int)t.TotalDays}d";
    }
}
