using AMREZ.EOP.Abstractions.Applications.Tenancy; using AMREZ.EOP.Abstractions.Applications.UseCases.Authentications; using AMREZ.EOP.Abstractions.Applications.UseCases.HumanResources; using AMREZ.EOP.Abstractions.Applications.UseCases.Payments.SlipVerification; using AMREZ.EOP.Abstractions.Applications.UseCases.Payments.SlipVerification.QrDecode; using AMREZ.EOP.Abstractions.Applications.UseCases.Tenancy; using AMREZ.EOP.Abstractions.Infrastructures.Common; using AMREZ.EOP.Abstractions.Infrastructures.Integrations.SCB.Clients; using AMREZ.EOP.Abstractions.Infrastructures.Repositories; using AMREZ.EOP.Abstractions.Security; using AMREZ.EOP.Abstractions.Storage; using AMREZ.EOP.Application.UseCases.Authentications; using AMREZ.EOP.Application.UseCases.HumanResources; using AMREZ.EOP.Application.UseCases.Payments.SlipVerification; using AMREZ.EOP.Application.UseCases.Payments.SlipVerification.BankDetect; using AMREZ.EOP.Application.UseCases.Payments.SlipVerification.QrDecode; using AMREZ.EOP.Application.UseCases.Tenancy; using AMREZ.EOP.Domain.Shared.Payments; using AMREZ.EOP.Domain.Shared.Tenancy; using AMREZ.EOP.Infrastructures.Data; using AMREZ.EOP.Infrastructures.Integrations.SCB.Clients; using AMREZ.EOP.Infrastructures.Options; using AMREZ.EOP.Infrastructures.Repositories; using AMREZ.EOP.Infrastructures.Security; using AMREZ.EOP.Infrastructures.Storage; using AMREZ.EOP.Infrastructures.Tenancy; using AMREZ.EOP.Infrastructures.UnitOfWork; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using StackExchange.Redis; namespace AMREZ.EOP.Infrastructures.DependencyInjections; public static class ServiceCollectionExtensions { public static IServiceCollection AddInfrastructure(this IServiceCollection services) { services.AddHttpContextAccessor(); services.AddScoped(); services.AddSingleton(new SCBOptions()); services.AddHttpClient((sp, http) => { var o = sp.GetRequiredService(); var baseUrl = o.BaseUrl.EndsWith('/') ? o.BaseUrl[..^1] : o.BaseUrl; http.BaseAddress = new Uri(baseUrl + "/v1/"); http.Timeout = TimeSpan.FromSeconds(20); }); // Options services.AddOptions() .BindConfiguration("Connections") .ValidateOnStart(); // Tenancy core (order matters for AddDbContext factory resolution) services.AddSingleton(sp => { var map = new TenantMap(); var opts = sp.GetRequiredService>().Value; map.UpsertTenant("public", new TenantContext { Id = "public", Schema = "public", ConnectionString = string.IsNullOrWhiteSpace(opts.DefaultConnection) ? null : opts.DefaultConnection, Mode = TenantMode.Rls }); return map; }); services.AddHostedService(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); // DbContext (attach RLS/search_path interceptors) services.AddDbContext((sp, o) => { var cfg = sp.GetRequiredService>().Value; o.UseNpgsql(cfg.DefaultConnection); o.AddInterceptors( sp.GetRequiredService(), sp.GetRequiredService() ); }); // Db scope / UoW services.AddScoped(); services.AddScoped(); services.AddScoped(); // Security services.AddScoped(); // Repositories — Auth & HR แยกกัน services.AddScoped(); services.AddScoped(); services.AddScoped(); // UseCases — Authentication services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); // UseCases — HR services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); // UseCases — Tenancy services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); // UseCase & helpers (no OCR) services.AddScoped(); services.AddScoped(); // Redis (optional) services.AddSingleton(sp => { var opts = sp.GetRequiredService>().Value; var conn = opts.RedisConnection; if (string.IsNullOrWhiteSpace(conn)) return null; try { var cfg = ConfigurationOptions.Parse(conn, true); cfg.AbortOnConnectFail = false; cfg.ConnectTimeout = 1000; cfg.SyncTimeout = 1000; var mux = ConnectionMultiplexer.Connect(cfg); return mux.IsConnected ? mux : null; } catch { return null; } }); return services; } }