using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.StaticFiles;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;

namespace GmRelay.Web.Services.Portfolio.Covers;

public static class PortfolioCoverStorageExtensions
{
    public static IServiceCollection AddPortfolioCoverStorage(
        this IServiceCollection services,
        IConfiguration configuration)
    {
        ArgumentNullException.ThrowIfNull(services);
        ArgumentNullException.ThrowIfNull(configuration);

        services
            .AddOptions<PortfolioCoverStorageOptions>()
            .Bind(configuration.GetSection(PortfolioCoverStorageOptions.SectionName))
            .Validate(
                o => !string.IsNullOrWhiteSpace(o.StoragePath),
                "PortfolioCovers:StoragePath must be configured.")
            .ValidateOnStart();

        services.AddSingleton<IPortfolioCoverStorage>(sp =>
        {
            var options = sp.GetRequiredService<
                Microsoft.Extensions.Options.IOptions<PortfolioCoverStorageOptions>>().Value;
            var logger = sp.GetService<ILoggerFactory>()?.CreateLogger<LocalPortfolioCoverStorage>()
                ?? NullLogger<LocalPortfolioCoverStorage>.Instance;
            return new LocalPortfolioCoverStorage(options, logger);
        });

        return services;
    }

    public static WebApplication UsePortfolioCoverFiles(this WebApplication app)
    {
        ArgumentNullException.ThrowIfNull(app);

        var options = app.Services.GetRequiredService<
            Microsoft.Extensions.Options.IOptions<PortfolioCoverStorageOptions>>().Value;

        var storagePath = Path.IsPathRooted(options.StoragePath)
            ? options.StoragePath
            : Path.Combine(app.Environment.ContentRootPath, options.StoragePath);

        Directory.CreateDirectory(storagePath);

        var contentTypeProvider = new FileExtensionContentTypeProvider();
        if (!contentTypeProvider.Mappings.ContainsKey(".jpg"))
        {
            contentTypeProvider.Mappings[".jpg"] = "image/jpeg";
        }

        if (!contentTypeProvider.Mappings.ContainsKey(".png"))
        {
            contentTypeProvider.Mappings[".png"] = "image/png";
        }

        if (!contentTypeProvider.Mappings.ContainsKey(".webp"))
        {
            contentTypeProvider.Mappings[".webp"] = "image/webp";
        }

        app.UseStaticFiles(new StaticFileOptions
        {
            FileProvider = new PhysicalFileProvider(storagePath),
            RequestPath = "/portfolio-covers",
            ContentTypeProvider = contentTypeProvider,
            OnPrepareResponse = ctx =>
            {
                ctx.Context.Response.Headers["Cache-Control"] = "public, max-age=31536000, immutable";
            }
        });

        return app;
    }
}
