using CashLineERP.Contracts.Notifications;

namespace CashLineERP.Application.Notifications;

public sealed class NotificationOrchestrationService : INotificationOrchestrationService
{
    private readonly INotificationOrchestrationRepository _repository;

    public NotificationOrchestrationService(INotificationOrchestrationRepository repository)
    {
        _repository = repository;
    }

    public IReadOnlyCollection<NotificationQueueItemResponse> GetQueueItems(string? statusCode = null, string? channelCode = null) =>
        _repository.GetQueueItems(statusCode, channelCode).Select(Map).ToArray();

    public NotificationQueueItemResponse? GetQueueItem(long notificationQueueItemId)
    {
        var item = _repository.GetQueueItem(notificationQueueItemId);
        return item is null ? null : Map(item);
    }

    public NotificationQueueItemResponse EnqueueNotification(long actorUserId, EnqueueNotificationRequest request) =>
        Map(_repository.Enqueue(new EnqueueNotificationCommand(
            actorUserId,
            request.NotificationTemplateId,
            request.RecipientReference,
            request.ContextCode,
            request.RelatedEntityType,
            request.RelatedEntityId,
            request.Variables ?? new Dictionary<string, string?>())));

    public NotificationSendBatchResultResponse SendPendingBatch(NotificationSendBatchRequest request)
    {
        var result = _repository.SendPendingBatch(new NotificationSendBatchCommand(
            request.SenderCode,
            request.BatchSize));

        return new NotificationSendBatchResultResponse(
            result.SenderCode,
            result.RequestedBatchSize,
            result.SentCount,
            result.SentItems.Select(Map).ToArray());
    }

    public NotificationQueueItemResponse MoveQueueItemToDeadLetter(long notificationQueueItemId, long actorUserId, NotificationDeadLetterRequest request) =>
        Map(_repository.MoveToDeadLetter(notificationQueueItemId, actorUserId, request.ReasonText));

    public NotificationQueueItemResponse ReplayQueueItem(long notificationQueueItemId, long actorUserId, NotificationReplayRequest request) =>
        Map(_repository.Replay(notificationQueueItemId, actorUserId, request.ReplayReasonText, request.DelaySeconds));

    private static NotificationQueueItemResponse Map(NotificationQueueItemDetailView item) =>
        new(
            item.NotificationQueueItemId,
            item.NotificationTemplateId,
            item.TemplateCode,
            item.ChannelCode,
            item.RecipientReference,
            item.ContextCode,
            item.RelatedEntityType,
            item.RelatedEntityId,
            item.Subject,
            item.Body,
            item.StatusCode,
            item.AttemptNumber,
            item.LastAttemptAtUtc,
            item.NextAttemptAtUtc,
            item.SentAtUtc,
            item.SentByProcess,
            item.ErrorText,
            item.CreatedAtUtc,
            item.CreatedByUserId);
}
