using JSMR.Application.DI;
using JSMR.Infrastructure.Data;
using JSMR.Infrastructure.DI;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Http.Json;
using Microsoft.EntityFrameworkCore;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace JSMR.Api.Startup;

public static class ServiceCollectionExtensions
{
    public static IServiceCollection AddAppServices(this IServiceCollection services, IConfigurationManager configuration)
    {
        services
            .AddMemoryCache()
            .AddApplication()
            .AddInfrastructure();

        string connectionString = configuration.GetConnectionString("AppDb")
                 ?? throw new InvalidOperationException("Missing ConnectionStrings:AppDb");

        services.AddDbContextFactory<AppDbContext>(opt =>
            opt.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString), mySqlOptions =>
            {
                mySqlOptions.CommandTimeout(120);
            })
            .EnableSensitiveDataLogging(false));

        services.AddControllers();

        return services;
    }

    public static IServiceCollection AddAppJson(this IServiceCollection services)
    {
        services.Configure<JsonOptions>(options =>
        {
            options.SerializerOptions.PropertyNameCaseInsensitive = true;
            options.SerializerOptions.Converters.Add(
                new JsonStringEnumConverter(JsonNamingPolicy.CamelCase));
        });

        return services;
    }

    public static IServiceCollection AddAppOpenApi(this IServiceCollection services)
    {
        services.AddOpenApi();

        return services;
    }

    public static IServiceCollection AddAppAuthentication(this IServiceCollection services, IHostEnvironment environment)
    {
        services.AddAuthorization();

        services
            .AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
            .AddCookie(options =>
            {
                options.Cookie.Name = "vw_auth";
                options.Cookie.HttpOnly = true;
                //options.Cookie.SameSite = SameSiteMode.None;
                //options.Cookie.SecurePolicy = CookieSecurePolicy.Always;

                options.Cookie.SameSite = SameSiteMode.Lax;

                options.Cookie.SecurePolicy =
                    environment.IsDevelopment()
                        ? CookieSecurePolicy.SameAsRequest
                        : CookieSecurePolicy.Always;

                options.Events = new CookieAuthenticationEvents
                {
                    OnRedirectToLogin = ctx =>
                    {
                        ctx.Response.StatusCode = StatusCodes.Status401Unauthorized;
                        return Task.CompletedTask;
                    },
                    OnRedirectToAccessDenied = ctx =>
                    {
                        ctx.Response.StatusCode = StatusCodes.Status403Forbidden;
                        return Task.CompletedTask;
                    }
                };
            });

        return services;
    }

    public static IServiceCollection AddAppCors(this IServiceCollection services, IConfigurationManager configuration)
    {
        string[] origins = configuration.GetSection("Cors:AllowedOrigins").Get<string[]>() ?? [];

        services.AddCors(options =>
        {
            options.AddPolicy("ui", policyBuilder =>
            {
                if (origins.Length == 0)
                {
                    // In container/prod you often don't need CORS at all (same-origin),
                    // but if it *is* needed and not configured, fail closed rather than crash.
                    // Do not call WithOrigins().
                    return;
                }

                policyBuilder.WithOrigins(origins)
                 .AllowAnyHeader()
                 .AllowAnyMethod()
                 .AllowCredentials();
            });
        });

        return services;
    }

    //public static IServiceCollection AddAppLogging(this IServiceCollection services, IHostApplicationBuilder builder)
    //{
    //    var config = builder.Configuration;
    //    var env = builder.Environment;

    //    Log.Logger = new LoggerConfiguration()
    //        .ReadFrom.Configuration(config)
    //        .MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
    //        .Enrich.WithProperty("Service", "JSMR.Api")
    //        .Enrich.WithProperty("Environment", env.EnvironmentName)
    //        .CreateLogger();

    //    return services;
    //}
}