using KArtSell.BuildingBlocks.Versioning;

namespace KArtSell.Modules.ModelOperations.Application;

public sealed record ApprovedModelContext(
    string ScopeKey,
    VersionSet VersionSet,
    string LifecycleState,
    DateTimeOffset EffectiveAt);

public sealed record DueModelOperation(
    Guid ScheduleId,
    string OperationCode,
    string ScopeKey,
    string Cadence,
    string AutomationMode,
    string Queue,
    string IdempotencyKey,
    int ScheduleVersion,
    int DispatchRevision,
    DateTimeOffset ScheduledFor,
    string CatchUpPolicy,
    int MaxCatchUp);

public sealed record ModelOperationRequest(
    Guid RequestId,
    Guid ScheduleId,
    string OperationCode,
    string ScopeKey,
    string AutomationMode,
    string IdempotencyKey,
    DateTimeOffset ScheduledFor,
    string CatchUpPolicy,
    int MaxCatchUp,
    ApprovedModelContext Context,
    string CorrelationId,
    DateTimeOffset RequestedAt);

public interface IApprovedModelContextReader
{
    Task<ApprovedModelContext?> ReadAsync(string scopeKey, DateTimeOffset asOf, CancellationToken cancellationToken);
}

public interface IModelScheduleRepository
{
    Task<IReadOnlyList<DueModelOperation>> AcquireDueAsync(
        DateTimeOffset now,
        string leaseOwner,
        TimeSpan leaseDuration,
        int limit,
        CancellationToken cancellationToken);

    Task MarkDispatchedAsync(
        Guid scheduleId,
        string leaseOwner,
        int expectedDispatchRevision,
        string backgroundJobId,
        DateTimeOffset dispatchedAt,
        DateTimeOffset nextDueAt,
        CancellationToken cancellationToken);

    Task AdvanceWithoutDispatchAsync(
        Guid scheduleId,
        string leaseOwner,
        int expectedDispatchRevision,
        DateTimeOffset advancedAt,
        DateTimeOffset nextDueAt,
        CancellationToken cancellationToken);

    Task ReleaseAsync(
        Guid scheduleId,
        string leaseOwner,
        int expectedDispatchRevision,
        string reasonCode,
        DateTimeOffset releasedAt,
        CancellationToken cancellationToken);
}

public interface IModelOperationRequestRepository
{
    Task<bool> AddAsync(ModelOperationRequest request, CancellationToken cancellationToken);
}

public interface IModelOperationRequestService
{
    Task<ModelOperationRequest?> RequestAsync(
        Guid scheduleId,
        string operationCode,
        string scopeKey,
        string automationMode,
        string idempotencyKey,
        DateTimeOffset scheduledFor,
        string catchUpPolicy,
        int maxCatchUp,
        string correlationId,
        CancellationToken cancellationToken);
}
