using Books.Api.EventFlow.Repositories;

namespace Books.Api.Authorization;

/// <summary>
/// Middleware that extracts the X-Company-Id header and validates user access.
/// Stores the result in HttpContext.Items for use by GraphQL resolvers.
/// </summary>
public class CompanyContextMiddleware(RequestDelegate next)
{
    public const string HeaderName = "X-Company-Id";
    public const string ContextKey = "CompanyContext";

    public async Task InvokeAsync(HttpContext context, IUserCompanyAccessRepository accessRepository)
    {
        var companyContext = new CompanyContext();

        // Only process if user is authenticated
        if (context.User.Identity?.IsAuthenticated == true)
        {
            var userId = context.User.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier)?.Value;

            if (userId != null && context.Request.Headers.TryGetValue(HeaderName, out var companyIdHeader))
            {
                var companyId = companyIdHeader.ToString();

                if (!string.IsNullOrWhiteSpace(companyId))
                {
                    // Validate user has access to this company
                    var access = await accessRepository.GetAccessAsync(userId, companyId);

                    if (access != null)
                    {
                        companyContext = new CompanyContext
                        {
                            CompanyId = companyId,
                            Role = access.Role
                        };
                    }
                }
            }
        }

        // Store in HttpContext.Items for resolvers to access
        context.Items[ContextKey] = companyContext;

        await next(context);
    }
}

/// <summary>
/// Extension methods for accessing CompanyContext.
/// </summary>
public static class CompanyContextExtensions
{
    /// <summary>
    /// Get the CompanyContext from HttpContext.
    /// </summary>
    public static CompanyContext GetCompanyContext(this HttpContext context)
    {
        return context.Items[CompanyContextMiddleware.ContextKey] as CompanyContext
               ?? new CompanyContext();
    }

    /// <summary>
    /// Add the CompanyContext middleware to the pipeline.
    /// </summary>
    public static IApplicationBuilder UseCompanyContext(this IApplicationBuilder app)
    {
        return app.UseMiddleware<CompanyContextMiddleware>();
    }
}
