using Hangfire;
using KArtSell.Modules.ModelOperations.Application;
using Microsoft.Extensions.Logging;

namespace KArtSell.Modules.ModelOperations.Scheduling;

public sealed class ScheduledModelOperationJob(
    IModelOperationRequestService service,
    ILogger<ScheduledModelOperationJob> logger)
{
    private static readonly Action<ILogger, string, string, Exception?> LogModelOperationNotCreated =
        LoggerMessage.Define<string, string>(
            LogLevel.Warning,
            new EventId(1, nameof(LogModelOperationNotCreated)),
            "Model operation {OperationCode} for {ScopeKey} was not created because the approved frozen context is unavailable or the idempotency key already exists.");

    private static readonly Action<ILogger, string, string, string, string, Exception?> LogModelOperationRequested =
        LoggerMessage.Define<string, string, string, string>(
            LogLevel.Information,
            new EventId(2, nameof(LogModelOperationRequested)),
            "Requested model operation {OperationCode} for {ScopeKey} with model {ModelVersion} and dataset {DatasetId}. No model mutation is performed by this job.");

    [AutomaticRetry(Attempts = 3, OnAttemptsExceeded = AttemptsExceededAction.Fail)]
    public async Task ExecuteAsync(
        Guid scheduleId,
        string operationCode,
        string scopeKey,
        string automationMode,
        string idempotencyKey,
        DateTimeOffset scheduledFor,
        string catchUpPolicy,
        int maxCatchUp)
    {
        var correlationId = $"model-operation:{operationCode}:{Guid.NewGuid():N}";
        var request = await service.RequestAsync(
            scheduleId,
            operationCode,
            scopeKey,
            automationMode,
            idempotencyKey,
            scheduledFor,
            catchUpPolicy,
            maxCatchUp,
            correlationId,
            CancellationToken.None);

        if (request is null)
        {
            LogModelOperationNotCreated(logger, operationCode, scopeKey, null);
            return;
        }

        LogModelOperationRequested(
            logger,
            request.OperationCode,
            request.ScopeKey,
            request.Context.VersionSet.ModelVersion,
            request.Context.VersionSet.DatasetId,
            null);
    }
}
