using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Logging;

namespace PowderCoating.Web.Hubs;

/// <summary>
/// SignalR hub that delivers real-time shop floor updates to TV displays and worker devices.
/// Each connection is placed in a company-scoped group ("shop-{companyId}") so that job status
/// changes, batch assignments, and oven updates can be broadcast to all shop floor screens for
/// a tenant without leaking data to other companies.
/// </summary>
[Authorize]
public class ShopHub : Hub
{
    private readonly ILogger<ShopHub> _logger;

    /// <summary>
    /// Initializes a new instance of <see cref="ShopHub"/> with the required logger.
    /// </summary>
    public ShopHub(ILogger<ShopHub> logger)
    {
        _logger = logger;
    }

    /// <summary>
    /// Called by the SignalR framework when a shop floor client connects.
    /// Reads the CompanyId claim and adds the connection to the company-scoped shop group so that
    /// server-side broadcasts reach all screens for that company only.
    /// Errors are swallowed after logging to prevent a failed group join from dropping the connection.
    /// </summary>
    public override async Task OnConnectedAsync()
    {
        try
        {
            var companyId = Context.User?.FindFirst("CompanyId")?.Value;
            if (!string.IsNullOrEmpty(companyId))
                await Groups.AddToGroupAsync(Context.ConnectionId, $"shop-{companyId}");

            await base.OnConnectedAsync();
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error in ShopHub.OnConnectedAsync for connection {ConnectionId}", Context.ConnectionId);
        }
    }

    /// <summary>
    /// Called by the SignalR framework when a shop floor client disconnects.
    /// Unexpected disconnects (e.g., TV display losing network) are logged at Warning level so
    /// they can be correlated with shop floor connectivity issues without flooding the error log.
    /// </summary>
    public override async Task OnDisconnectedAsync(Exception? exception)
    {
        if (exception != null)
            _logger.LogWarning(exception, "ShopHub client disconnected with error: {ConnectionId}", Context.ConnectionId);

        await base.OnDisconnectedAsync(exception);
    }
}
