using Eis.Application.Authentication;
using Eis.Application.Administration;
using Eis.Application.Candidate;
using Eis.Application.Public;
using Eis.Infrastructure.Authentication;
using Eis.Infrastructure.Administration;
using Eis.Infrastructure.Candidate;
using Eis.Infrastructure.Caching;
using Eis.Infrastructure.Data;
using Eis.Infrastructure.Public;
using Eis.Infrastructure.Security;
using Microsoft.Extensions.DependencyInjection;

namespace Eis.Infrastructure;

public static class DependencyInjection
{
    public static void EnsureNativeAuthenticationReady(
        this IServiceProvider serviceProvider,
        AuthenticationOptions authenticationOptions)
    {
        if (authenticationOptions.NativeEnabled)
        {
            _ = serviceProvider.GetRequiredService<IAuthenticationStateStore>();
        }
    }

    public static IServiceCollection AddEisInfrastructure(
        this IServiceCollection services,
        DatabaseOptions databaseOptions,
        DocumentVerificationOptions documentVerificationOptions,
        AuthenticationOptions authenticationOptions,
        CandidateMigrationOptions candidateMigrationOptions,
        AdminMigrationOptions adminMigrationOptions)
    {
        services.AddSingleton(databaseOptions);
        services.AddSingleton<IRelationalConnectionFactory, RelationalConnectionFactory>();
        services.AddScoped<DatabaseInitializer>();
        services.AddSingleton<IApplicationCache, ApplicationCache>();
        services.AddSingleton(documentVerificationOptions);
        services.AddSingleton<DocumentVerificationCodeService>();
        services.AddSingleton(authenticationOptions);
        services.AddSingleton<PasswordCompatibilityService>();
        services.AddSingleton<TotpCompatibilityService>();
        services.AddSingleton<IAuthenticationStateStore>(provider =>
            authenticationOptions.UsesRedis
                ? new RedisAuthenticationStateStore(authenticationOptions)
                : new MemoryAuthenticationStateStore(authenticationOptions));
        services.AddScoped<AuthenticationRepository>();
        services.AddScoped<IAuthenticationService, AuthenticationService>();
        services.AddSingleton(candidateMigrationOptions);
        services.AddSingleton<RegionCatalog>();
        services.AddScoped<CandidateReadSnapshotLoader>();
        services.AddScoped<CandidateWriteRepository>();
        services.AddScoped<CandidateAdmissionRepository>();
        services.AddScoped<ICandidateService, CandidateService>();
        services.AddSingleton(adminMigrationOptions);
        services.AddScoped<AdminReadSnapshotLoader>();
        services.AddScoped<AdminWriteRepository>();
        services.AddScoped<AdminAccountBatchSnapshotLoader>();
        services.AddScoped<AdminAccountBatchRepository>();
        services.AddScoped<AdminConfigurationRepository>();
        services.AddScoped<AdminNoticeRepository>();
        services.AddScoped<AdminCenterSnapshotLoader>();
        services.AddScoped<AdminCenterRepository>();
        services.AddScoped<AdminOperationalSnapshotLoader>();
        services.AddScoped<AdminWorkflowResultSnapshotLoader>();
        services.AddScoped<AdminWorkflowRepository>();
        services.AddScoped<AdminExamRepository>();
        services.AddScoped<AdminArrangementSnapshotLoader>();
        services.AddScoped<AdminArrangementRepository>();
        services.AddScoped<AdminResultRepository>();
        services.AddScoped<AdminResultStatisticsBackfillService>();
        services.AddScoped<AdminAdmissionRepository>();
        services.AddScoped<IAdminReadService, AdminReadService>();
        services.AddScoped<IAdminOrganizationService, AdminOrganizationService>();
        services.AddScoped<IAdminAccountBatchService, AdminAccountBatchService>();
        services.AddScoped<IAdminConfigurationService, AdminConfigurationService>();
        services.AddScoped<IAdminNoticeService, AdminNoticeService>();
        services.AddScoped<IAdminCenterService, AdminCenterService>();
        services.AddScoped<IAdminOperationalReadService, AdminOperationalReadService>();
        services.AddScoped<IAdminCandidateManagementService, AdminCandidateManagementService>();
        services.AddScoped<IAdminRegistrationManagementService, AdminRegistrationManagementService>();
        services.AddScoped<IAdminWorkflowService, AdminWorkflowService>();
        services.AddScoped<IAdminExamManagementService, AdminExamManagementService>();
        services.AddScoped<IAdminArrangementService, AdminArrangementService>();
        services.AddScoped<IAdminResultService, AdminResultService>();
        services.AddScoped<IAdminAdmissionService, AdminAdmissionService>();
        services.AddScoped<IAdminExcelService, AdminExcelService>();
        services.AddSingleton<NoticeContentFormatter>();
        services.AddScoped<IPublicQueryService, PublicQueryService>();
        return services;
    }
}
