using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.OpenApi;

namespace DysonNetwork.Shared.Networking;

public static class SwaggerGen
{
    public static WebApplicationBuilder AddSwaggerManifest(
        this WebApplicationBuilder builder,
        string serviceName,
        string? serviceDescription
    )
    {
        builder.Services.AddEndpointsApiExplorer();
        builder.Services.AddSwaggerGen(options =>
        {
            options.SwaggerDoc("v1", new OpenApiInfo
            {
                Version = "v1",
                Title = serviceName,
                Description = serviceDescription,
                TermsOfService = new Uri("https://solsynth.dev/terms"),
                License = new OpenApiLicense
                {
                    Name = "APGLv3",
                    Url = new Uri("https://www.gnu.org/licenses/agpl-3.0.html")
                }
            });
            options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
            {
                In = ParameterLocation.Header,
                Description = "Solar Network Unified Authentication",
                Name = "Authorization",
                Type = SecuritySchemeType.Http,
                BearerFormat = "JWT",
                Scheme = "Bearer"
            });
        });
        builder.Services.AddOpenApi();

        return builder;
    }

    public static WebApplication UseSwaggerManifest(this WebApplication app, string serviceName)
    {
        app.MapOpenApi();
        
        var configuration = app.Configuration;
        app.UseSwagger(c =>
        {
            c.PreSerializeFilters.Add((swaggerDoc, httpReq) =>
            {
                var publicBasePath = configuration["Swagger:PublicBasePath"]?.TrimEnd('/') ?? "";

                // Rewrite all path keys (remove /api or replace it)
                var newPaths = new OpenApiPaths();
                foreach (var (path, pathItem) in swaggerDoc.Paths)
                {
                    // e.g. original path = "/api/drive/chunk/{taskId}/{chunkIndex}"
                    // We want to produce "/sphere/drive/chunk/{taskId}/{chunkIndex}" or maybe "/sphere/chunk/..."
                    var newPathKey = path;

                    // If "path" starts with "/api", strip it
                    if (newPathKey.StartsWith("/api", StringComparison.OrdinalIgnoreCase))
                    {
                        newPathKey = newPathKey["/api".Length..];
                        if (!newPathKey.StartsWith("/"))
                            newPathKey = "/" + newPathKey;
                    }

                    // Then prepend the public base path (if not root)
                    if (!string.IsNullOrEmpty(publicBasePath) && publicBasePath != "/")
                    {
                        // ensure slash composition
                        newPathKey = publicBasePath.TrimEnd('/') + newPathKey;
                    }

                    newPaths.Add(newPathKey, pathItem);
                }

                swaggerDoc.Paths = newPaths;
            });
        });

        app.UseSwaggerUI(options =>
        {
            // Swagger UI must point to the JSON location
            var publicBasePath = configuration["Swagger:PublicBasePath"]?.TrimEnd('/') ?? "";
            options.SwaggerEndpoint(
                $"{publicBasePath}/swagger/v1/swagger.json",
                $"{serviceName} API v1");
        });

        return app;
    }
}