using Microsoft.AspNetCore.SignalR;

namespace foodmarket.Api.Realtime;

/// <summary>Тонкий обёрточный сервис: контроллеры/сервисы вызывают
/// <see cref="PublishAsync(Guid, string, object)"/>, а доставка идёт через
/// <see cref="NotificationsHub"/> в группу <c>org:{Id}</c>.
///
/// Метод JSON-сериализуется в SignalR'е автоматически (System.Text.Json).
/// Имя метода = ключ для подписки на клиенте.</summary>
public interface INotificationsPublisher
{
    /// <summary>Шлём всем подключённым сессиям одной org-и событие.</summary>
    Task PublishAsync(Guid orgId, string method, object payload);
}

public sealed class NotificationsPublisher : INotificationsPublisher
{
    private readonly IHubContext<NotificationsHub> _hub;
    public NotificationsPublisher(IHubContext<NotificationsHub> hub) => _hub = hub;

    public Task PublishAsync(Guid orgId, string method, object payload)
        => _hub.Clients.Group(NotificationsHub.GroupName(orgId)).SendAsync(method, payload);
}

/// <summary>DTO событий — стабильные имена для контракта с фронтом.</summary>
public static class NotificationEvents
{
    /// <summary>Сразу после успешного post-a розничной продажи.</summary>
    public const string SalePosted = "SalePosted";
    /// <summary>Сразу после успешного post-a приёмки.</summary>
    public const string SupplyPosted = "SupplyPosted";
    /// <summary>Когда после движения остаток продукта стал ниже MinStock.
    /// Один event на каждый продукт-склад, в котором факт пересечения
    /// порога. Шлётся только когда было «выше» и стало «ниже» — иначе на
    /// каждой продаже сыпались бы тосты.</summary>
    public const string LowStock = "LowStock";
}

public sealed record SalePostedPayload(
    Guid SaleId,
    string Number,
    decimal Total,
    Guid StoreId,
    string? CashierName,
    Guid? RetailPointId,
    DateTime PostedAt);

public sealed record SupplyPostedPayload(
    Guid SupplyId,
    string Number,
    decimal Total,
    Guid SupplierId,
    string? SupplierName,
    DateTime PostedAt);

public sealed record LowStockPayload(
    Guid ProductId,
    string ProductName,
    Guid StoreId,
    string? StoreName,
    decimal Quantity,
    decimal MinStock);
