using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

namespace Baya.WebFramework.ServiceConfiguration;

public static class CorsServiceExtension
{
    /// <summary>The single named CORS policy the browser SPA is allowed through. Registered in DI by
    /// <see cref="AddCorsPolicies"/> and applied in the pipeline by <c>app.UseCors(PolicyName)</c>.</summary>
    public const string PolicyName = "BalinyaarWebClient";

    /// <summary>Configuration key holding the allowed browser origins (a string array).</summary>
    public const string AllowedOriginsKey = "Cors:AllowedOrigins";

    /// <summary>Fallback origin when <see cref="AllowedOriginsKey"/> is unset — the Next.js client's default
    /// dev URL. A deployed environment lists its real web origin(s) in configuration.</summary>
    private const string DefaultDevelopmentOrigin = "http://localhost:3000";

    // The client (client/src/lib/api/client.ts + the payment hooks) sets exactly these request headers on
    // its cross-origin calls; the pre-flight response must echo them back or the browser blocks the real
    // request. Kept explicit rather than AllowAnyHeader so the surface is auditable.
    private static readonly string[] AllowedHeaders =
    [
        "Authorization",
        "Content-Type",
        "Accept-Language",
        "Idempotency-Key"
    ];

    /// <summary>
    /// Registers the browser CORS policy from <see cref="AllowedOriginsKey"/> (a string array), falling back
    /// to the Next.js dev origin when unset so Development is permissive to localhost only. Credentials are
    /// NOT allowed: the client authenticates with a bearer <c>Authorization</c> header, not a cookie, so
    /// <c>AllowCredentials()</c> is unnecessary — and combining it with a wildcard origin is forbidden by the
    /// CORS spec anyway. Pair with <c>app.UseCors(<see cref="PolicyName"/>)</c> placed after
    /// <c>UseRouting()</c> and before the rate limiter / authentication, so a pre-flight OPTIONS is answered
    /// before those run.
    /// </summary>
    public static IServiceCollection AddCorsPolicies(this IServiceCollection services, IConfiguration configuration)
    {
        var origins = configuration.GetSection(AllowedOriginsKey).Get<string[]>();
        if (origins is null || origins.Length == 0)
            origins = [DefaultDevelopmentOrigin];

        services.AddCors(options =>
        {
            options.AddPolicy(PolicyName, policy =>
                policy.WithOrigins(origins)
                    .WithHeaders(AllowedHeaders)
                    .AllowAnyMethod());
        });

        return services;
    }
}
