using CashLineERP.Contracts.Integration;

namespace CashLineERP.Application.Integration;

public sealed class OutboxEventService : IOutboxEventService
{
    private readonly IOutboxEventRepository _repository;

    public OutboxEventService(IOutboxEventRepository repository)
    {
        _repository = repository;
    }

    public IReadOnlyCollection<OutboxEventResponse> GetOutboxEvents(
        string? statusCode = null,
        string? sourceModuleCode = null) =>
        _repository.GetOutboxEvents(statusCode, sourceModuleCode)
            .Select(Map)
            .ToArray();

    public OutboxEventResponse? GetOutboxEvent(long outboxEventId)
    {
        var outboxEvent = _repository.GetOutboxEvent(outboxEventId);
        return outboxEvent is null ? null : Map(outboxEvent);
    }

    public PublishOutboxBatchResultResponse PublishPendingEvents(PublishOutboxBatchRequest request) =>
        Map(_repository.PublishPendingEvents(new PublishOutboxBatchCommand(
            request.PublisherCode,
            request.BatchSize)));

    public OutboxEventResponse MoveOutboxEventToDeadLetter(long outboxEventId, long actorUserId, DeadLetterQueueItemRequest request) =>
        Map(_repository.MoveToDeadLetter(outboxEventId, actorUserId, request.ReasonText));

    public OutboxEventResponse ReplayOutboxEvent(long outboxEventId, long actorUserId, ReplayDeadLetterQueueItemRequest request) =>
        Map(_repository.Replay(outboxEventId, actorUserId, request.ReplayReasonText, request.DelaySeconds));

    private static OutboxEventResponse Map(OutboxEventDetailView outboxEvent) =>
        new(
            outboxEvent.OutboxEventId,
            outboxEvent.EventNumber,
            outboxEvent.SourceModuleCode,
            outboxEvent.AggregateType,
            outboxEvent.AggregateId,
            outboxEvent.EventType,
            outboxEvent.CorrelationKey,
            outboxEvent.PayloadText,
            outboxEvent.StatusCode,
            outboxEvent.AttemptNumber,
            outboxEvent.AvailableAtUtc,
            outboxEvent.PublishedAtUtc,
            outboxEvent.PublishedByProcess,
            outboxEvent.LastErrorText,
            outboxEvent.CreatedAtUtc);

    private static PublishOutboxBatchResultResponse Map(PublishOutboxBatchResultView result) =>
        new(
            result.PublisherCode,
            result.RequestedBatchSize,
            result.PublishedCount,
            result.PublishedEvents.Select(Map).ToArray());
}
