// EN: Implementation of POS real-time notification service using SignalR.
// VI: Implementation dịch vụ thông báo real-time POS sử dụng SignalR.

using Microsoft.AspNetCore.SignalR;

namespace OrderService.API.Hubs;

/// <summary>
/// EN: Sends real-time notifications to POS/KDS clients via SignalR hub context.
/// VI: Gửi thông báo real-time đến POS/KDS clients qua SignalR hub context.
/// </summary>
public class PosNotificationService : IPosNotificationService
{
    private readonly IHubContext<PosHub, IPosHubClient> _hubContext;
    private readonly ILogger<PosNotificationService> _logger;

    public PosNotificationService(
        IHubContext<PosHub, IPosHubClient> hubContext,
        ILogger<PosNotificationService> logger)
    {
        _hubContext = hubContext ?? throw new ArgumentNullException(nameof(hubContext));
        _logger = logger ?? throw new ArgumentNullException(nameof(logger));
    }

    /// <inheritdoc/>
    public async Task NotifyOrderCreatedAsync(
        Guid shopId,
        OrderNotificationDto order,
        CancellationToken cancellationToken = default)
    {
        _logger.LogInformation(
            "EN: Sending OrderCreated notification for order {OrderId} to shop {ShopId} / " +
            "VI: Gửi thông báo OrderCreated cho order {OrderId} đến shop {ShopId}",
            order.OrderId, shopId);

        // EN: Send to both shop and pos groups / VI: Gửi đến cả group shop và pos
        await Task.WhenAll(
            _hubContext.Clients.Group($"shop:{shopId}").OrderCreated(order),
            _hubContext.Clients.Group($"pos:{shopId}").OrderCreated(order)
        );
    }

    /// <inheritdoc/>
    public async Task NotifyOrderUpdatedAsync(
        Guid shopId,
        OrderNotificationDto order,
        CancellationToken cancellationToken = default)
    {
        _logger.LogInformation(
            "EN: Sending OrderUpdated notification for order {OrderId} to shop {ShopId} / " +
            "VI: Gửi thông báo OrderUpdated cho order {OrderId} đến shop {ShopId}",
            order.OrderId, shopId);

        await _hubContext.Clients.Group($"shop:{shopId}").OrderUpdated(order);
    }

    /// <inheritdoc/>
    public async Task NotifyOrderStatusChangedAsync(
        Guid shopId,
        Guid orderId,
        string oldStatus,
        string newStatus,
        CancellationToken cancellationToken = default)
    {
        _logger.LogInformation(
            "EN: Sending OrderStatusChanged notification for order {OrderId}: {OldStatus} -> {NewStatus} / " +
            "VI: Gửi thông báo OrderStatusChanged cho order {OrderId}: {OldStatus} -> {NewStatus}",
            orderId, oldStatus, newStatus);

        var statusChange = new OrderStatusChangedDto(
            orderId,
            oldStatus,
            newStatus,
            DateTime.UtcNow);

        // EN: Send to all groups (shop, pos, kds) / VI: Gửi đến tất cả groups (shop, pos, kds)
        await Task.WhenAll(
            _hubContext.Clients.Group($"shop:{shopId}").OrderStatusChanged(statusChange),
            _hubContext.Clients.Group($"pos:{shopId}").OrderStatusChanged(statusChange),
            _hubContext.Clients.Group($"kds:{shopId}").OrderStatusChanged(statusChange)
        );
    }

    /// <inheritdoc/>
    public async Task NotifyKitchenTicketCreatedAsync(
        Guid shopId,
        KitchenTicketNotificationDto ticket,
        CancellationToken cancellationToken = default)
    {
        _logger.LogInformation(
            "EN: Sending KitchenTicketCreated notification for ticket {TicketId} to KDS shop {ShopId} / " +
            "VI: Gửi thông báo KitchenTicketCreated cho phiếu {TicketId} đến KDS shop {ShopId}",
            ticket.TicketId, shopId);

        // EN: Send to both shop and kds groups / VI: Gửi đến cả group shop và kds
        await Task.WhenAll(
            _hubContext.Clients.Group($"shop:{shopId}").KitchenTicketCreated(ticket),
            _hubContext.Clients.Group($"kds:{shopId}").KitchenTicketCreated(ticket)
        );
    }

    /// <inheritdoc/>
    public async Task NotifyKitchenTicketUpdatedAsync(
        Guid shopId,
        KitchenTicketNotificationDto ticket,
        CancellationToken cancellationToken = default)
    {
        _logger.LogInformation(
            "EN: Sending KitchenTicketUpdated notification for ticket {TicketId} to KDS shop {ShopId} / " +
            "VI: Gửi thông báo KitchenTicketUpdated cho phiếu {TicketId} đến KDS shop {ShopId}",
            ticket.TicketId, shopId);

        await Task.WhenAll(
            _hubContext.Clients.Group($"shop:{shopId}").KitchenTicketUpdated(ticket),
            _hubContext.Clients.Group($"kds:{shopId}").KitchenTicketUpdated(ticket)
        );
    }

    /// <inheritdoc/>
    public async Task NotifyPaymentCompletedAsync(
        Guid shopId,
        PaymentNotificationDto payment,
        CancellationToken cancellationToken = default)
    {
        _logger.LogInformation(
            "EN: Sending PaymentCompleted notification for order {OrderId} to shop {ShopId} / " +
            "VI: Gửi thông báo PaymentCompleted cho order {OrderId} đến shop {ShopId}",
            payment.OrderId, shopId);

        // EN: Send to both shop and pos groups / VI: Gửi đến cả group shop và pos
        await Task.WhenAll(
            _hubContext.Clients.Group($"shop:{shopId}").PaymentCompleted(payment),
            _hubContext.Clients.Group($"pos:{shopId}").PaymentCompleted(payment)
        );
    }

    /// <inheritdoc/>
    public async Task NotifyTableStatusChangedAsync(
        Guid shopId,
        TableStatusNotificationDto tableStatus,
        CancellationToken cancellationToken = default)
    {
        _logger.LogInformation(
            "EN: Sending TableStatusChanged notification for table {TableId} to shop {ShopId} / " +
            "VI: Gửi thông báo TableStatusChanged cho bàn {TableId} đến shop {ShopId}",
            tableStatus.TableId, shopId);

        // EN: Send to all groups / VI: Gửi đến tất cả groups
        await Task.WhenAll(
            _hubContext.Clients.Group($"shop:{shopId}").TableStatusChanged(tableStatus),
            _hubContext.Clients.Group($"pos:{shopId}").TableStatusChanged(tableStatus),
            _hubContext.Clients.Group($"kds:{shopId}").TableStatusChanged(tableStatus)
        );
    }
}
