using System.Security.Claims;
using foodmarket.Api.Infrastructure.Tenancy;
using Serilog.Context;

namespace foodmarket.Api.Infrastructure.Observability;

/// <summary>Обогащает каждый HTTP-запрос структурными лейблами в Serilog
/// LogContext: OrgId, UserId, CorrelationId. Любая ILogger.Log<…>
/// внутри пайплайна автоматически получит эти свойства — не надо
/// тащить их явно в каждый вызов.
///
/// CorrelationId: берётся из заголовка <c>X-Correlation-ID</c> если есть,
/// иначе генерируется Guid. Эхо в response-header чтобы клиент видел
/// id для последующего запроса в support.</summary>
public sealed class LogEnrichmentMiddleware
{
    private const string HeaderName = "X-Correlation-ID";
    private readonly RequestDelegate _next;

    public LogEnrichmentMiddleware(RequestDelegate next) => _next = next;

    public async Task InvokeAsync(HttpContext ctx)
    {
        var correlationId = ctx.Request.Headers.TryGetValue(HeaderName, out var hdr) && !string.IsNullOrWhiteSpace(hdr)
            ? hdr.ToString()
            : Guid.NewGuid().ToString("N");
        ctx.Response.Headers[HeaderName] = correlationId;

        var orgId = ctx.User?.FindFirst(HttpContextTenantContext.OrganizationClaim)?.Value;
        var userId = ctx.User?.FindFirst(ClaimTypes.NameIdentifier)?.Value
                  ?? ctx.User?.FindFirst("sub")?.Value;

        using var c = LogContext.PushProperty("CorrelationId", correlationId);
        using var o = orgId is null ? null : LogContext.PushProperty("OrgId", orgId);
        using var u = userId is null ? null : LogContext.PushProperty("UserId", userId);
        await _next(ctx);
    }
}
