using Jiaowu.Api.Domain.System;

namespace Jiaowu.Api.Infrastructure.BackgroundJobs;

public sealed class BackgroundJobOptions
{
    public const string SectionName = "BackgroundJobs";

    public string Transport { get; set; } = "InMemory";
    public int PollIntervalMilliseconds { get; set; } = 500;
    public int LeaseSeconds { get; set; } = 120;
    public ushort PrefetchCount { get; set; } = 1;
    public int AutomaticScheduleConcurrency { get; set; } = 1;
    public int SchedulePublishConcurrency { get; set; } = 1;
    public int MakeupExamAutoConcurrency { get; set; } = 1;
    public int ExamArrangementConcurrency { get; set; } = 1;
    public int ExamSignInExportConcurrency { get; set; } = 1;
    public int ExamPublishConcurrency { get; set; } = 1;
    public int CourseGradeStatisticsRefreshConcurrency { get; set; } = 1;
    public string Exchange { get; set; } = "jiaowu.background-jobs";
    public string QueuePrefix { get; set; } = "jiaowu.background-jobs";
    public bool UseQuorumQueues { get; set; } = true;
    public int ProcessingAttemptLimit { get; set; } = 5;
    public int MaintenanceIntervalSeconds { get; set; } = 60;
    public int CompletedRetentionDays { get; set; } = 14;
    public int CleanupBatchSize { get; set; } = 500;

    public bool UsesRabbitMq =>
        Transport.Equals("RabbitMq", StringComparison.OrdinalIgnoreCase);

    public int ConsumerConcurrency(BackgroundJobKind kind) => kind switch
    {
        BackgroundJobKind.AutomaticSchedule => AutomaticScheduleConcurrency,
        BackgroundJobKind.SchedulePublish => SchedulePublishConcurrency,
        BackgroundJobKind.MakeupExamAuto => MakeupExamAutoConcurrency,
        BackgroundJobKind.ExamArrangement => ExamArrangementConcurrency,
        BackgroundJobKind.ExamSignInExport => ExamSignInExportConcurrency,
        BackgroundJobKind.ExamPublish => ExamPublishConcurrency,
        BackgroundJobKind.CourseGradeStatisticsRefresh =>
            CourseGradeStatisticsRefreshConcurrency,
        _ => throw new ArgumentOutOfRangeException(nameof(kind), kind, null)
    };
}

public sealed class RabbitMqOptions
{
    public const string SectionName = "RabbitMq";

    public string HostName { get; set; } = "localhost";
    public int Port { get; set; } = 5672;
    public string UserName { get; set; } = "guest";
    public string Password { get; set; } = "guest";
    public string VirtualHost { get; set; } = "/";
    public bool UseTls { get; set; }
    public string? TlsServerName { get; set; }
}
