using System.Text;
using System.Text.Json.Serialization;
using FluentValidation;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using Meezi.Admin.API.Hubs;
using Meezi.Admin.API.Services;
using Meezi.Admin.API.Models;
using Meezi.Admin.API.Validators;
using Meezi.Infrastructure;
using Serilog;
using StackExchange.Redis;

namespace Meezi.Admin.API.Extensions;

public static class AdminServiceCollectionExtensions
{
    public static IServiceCollection AddMeeziAdminServices(
        this IServiceCollection services,
        IConfiguration configuration)
    {
        services.AddInfrastructure(configuration);

        services.AddScoped<IAdminAuthService, AdminAuthService>();
        services.AddScoped<IAdminJwtTokenService, AdminJwtTokenService>();
        services.AddSingleton<IRefreshTokenStore, RedisRefreshTokenStore>();
        services.AddScoped<IAdminPlatformService, AdminPlatformService>();
        services.AddScoped<IPlatformIntegrationService, PlatformIntegrationService>();
        services.AddScoped<IAdminNotificationService, AdminNotificationService>();
        services.AddScoped<IAdminWebsiteService, AdminWebsiteService>();

        services.AddControllers()
            .AddJsonOptions(options =>
            {
                options.JsonSerializerOptions.PropertyNamingPolicy = System.Text.Json.JsonNamingPolicy.CamelCase;
                options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
            });
        services.AddEndpointsApiExplorer();
        services.AddSwaggerGen();
        services.AddSignalR();
        services.AddValidatorsFromAssemblyContaining<SendOtpRequestValidator>();
        // Explicit registrations as safety net (assembly scan can miss in some Docker layer caches)
        services.AddScoped<IValidator<SendOtpRequest>, SendOtpRequestValidator>();
        services.AddScoped<IValidator<VerifyOtpRequest>, VerifyOtpRequestValidator>();
        services.AddScoped<IValidator<RefreshTokenRequest>, RefreshTokenRequestValidator>();

        var jwtKey = configuration["Jwt:Key"] ?? "meezi-dev-secret-key-min-32-chars!!";
        var jwtIssuer = configuration["Jwt:Issuer"] ?? "meezi";
        var jwtAudience = configuration["Jwt:Audience"] ?? "meezi-admin";

        services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
            .AddJwtBearer(options =>
            {
                options.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuer = true,
                    ValidateAudience = true,
                    ValidateLifetime = true,
                    ValidateIssuerSigningKey = true,
                    ValidIssuer = jwtIssuer,
                    ValidAudience = jwtAudience,
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtKey))
                };
            });

        services.AddAuthorization();

        var redisConnection = configuration.GetConnectionString("Redis") ?? "localhost:6379";
        services.AddSingleton<IConnectionMultiplexer>(_ =>
            ConnectionMultiplexer.Connect($"{redisConnection},abortConnect=false"));

        services.AddCors(options =>
        {
            options.AddPolicy("AdminCors", policy =>
            {
                var origins = configuration.GetSection("Cors:Origins").Get<string[]>()
                    ?? ["http://localhost:3102"];
                policy.WithOrigins(origins)
                    .AllowAnyHeader()
                    .AllowAnyMethod()
                    .AllowCredentials();
            });
        });

        return services;
    }

    public static WebApplication ConfigureMeeziAdminPipeline(this WebApplication app)
    {
        app.UseSerilogRequestLogging();

        if (app.Environment.IsDevelopment())
        {
            app.UseSwagger();
            app.UseSwaggerUI();
        }

        app.UseHttpsRedirection();
        app.UseCors("AdminCors");
        app.UseAuthentication();
        app.UseMiddleware<Middleware.AdminTenantMiddleware>();
        app.UseAuthorization();
        app.MapControllers();
        app.MapHub<KdsHub>("/hubs/kds");
        app.MapGet("/health", () => Results.Ok(new { status = "healthy", service = "meezi-admin-api" }));

        return app;
    }
}
