using ColaFlow.Modules.Identity.Application.Services;
using ColaFlow.Modules.Identity.Domain.Repositories;
using ColaFlow.Modules.Identity.Infrastructure.Persistence;
using ColaFlow.Modules.Identity.Infrastructure.Persistence.Repositories;
using ColaFlow.Modules.Identity.Infrastructure.Services;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace ColaFlow.Modules.Identity.Infrastructure;

public static class DependencyInjection
{
    public static IServiceCollection AddIdentityInfrastructure(
        this IServiceCollection services,
        IConfiguration configuration,
        IHostEnvironment? environment = null)
    {
        // Only register PostgreSQL DbContext in non-Testing environments
        // In Testing environment, WebApplicationFactory will register InMemory provider
        if (environment == null || environment.EnvironmentName != "Testing")
        {
            // DbContext (using connection string)
            services.AddDbContext<IdentityDbContext>(options =>
                options.UseNpgsql(
                    configuration.GetConnectionString("DefaultConnection"),
                    b => b.MigrationsAssembly(typeof(IdentityDbContext).Assembly.FullName)));
        }

        // Tenant Context (Scoped - one instance per request)
        services.AddScoped<ITenantContext, TenantContext>();
        services.AddHttpContextAccessor(); // Required for HttpContext access

        // Repositories
        services.AddScoped<ITenantRepository, TenantRepository>();
        services.AddScoped<IUserRepository, UserRepository>();
        services.AddScoped<IRefreshTokenRepository, RefreshTokenRepository>();
        services.AddScoped<IUserTenantRoleRepository, UserTenantRoleRepository>();
        services.AddScoped<IEmailVerificationTokenRepository, EmailVerificationTokenRepository>();
        services.AddScoped<IPasswordResetTokenRepository, PasswordResetTokenRepository>();
        services.AddScoped<IInvitationRepository, InvitationRepository>();

        // Application Services
        services.AddScoped<IJwtService, JwtService>();
        services.AddScoped<IPasswordHasher, PasswordHasher>();
        services.AddScoped<IRefreshTokenService, RefreshTokenService>();
        services.AddScoped<ISecurityTokenService, SecurityTokenService>();

        // Database-backed rate limiting (replaces in-memory implementation)
        // Persists rate limit state to survive server restarts and prevent email bombing attacks
        services.AddScoped<IRateLimitService, DatabaseEmailRateLimiter>();

        // Email Services
        var emailProvider = configuration["Email:Provider"] ?? "Mock";
        if (emailProvider.Equals("Mock", StringComparison.OrdinalIgnoreCase))
        {
            services.AddSingleton<IEmailService, MockEmailService>();
        }
        else
        {
            services.AddScoped<IEmailService, SmtpEmailService>();
        }
        services.AddScoped<IEmailTemplateService, EmailTemplateService>();

        return services;
    }
}
