using Microsoft.AspNetCore.Http;

namespace SIGCM2.Api.Middleware;

/// UDT-010 — pre-auth middleware that stamps every request with a correlation ID,
/// preserves one sent by the client via X-Correlation-Id, and exposes it on the response.
/// Also captures Ip + UserAgent for downstream IAuditContext consumers.
public sealed class CorrelationIdMiddleware
{
    public const string HeaderName = "X-Correlation-Id";
    public const string ItemCorrelationId = "audit:correlationId";
    public const string ItemIp = "audit:ip";
    public const string ItemUserAgent = "audit:userAgent";

    private readonly RequestDelegate _next;

    public CorrelationIdMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task InvokeAsync(HttpContext ctx)
    {
        Guid correlationId;
        if (ctx.Request.Headers.TryGetValue(HeaderName, out var incoming)
            && Guid.TryParse(incoming.ToString(), out var parsed))
        {
            correlationId = parsed;
        }
        else
        {
            correlationId = Guid.NewGuid();
        }

        ctx.Items[ItemCorrelationId] = correlationId;
        ctx.Items[ItemIp] = ctx.Connection.RemoteIpAddress?.ToString();
        ctx.Items[ItemUserAgent] = ctx.Request.Headers.UserAgent.ToString();

        ctx.Response.OnStarting(() =>
        {
            ctx.Response.Headers[HeaderName] = correlationId.ToString("D");
            return Task.CompletedTask;
        });

        // Also set immediately for testability — DefaultHttpContext does not trigger OnStarting
        // in unit tests because no body is written through the pipeline.
        ctx.Response.Headers[HeaderName] = correlationId.ToString("D");

        await _next(ctx);
    }
}
