using CashLineERP.Application.Integration;
using Microsoft.EntityFrameworkCore;

namespace CashLineERP.Infrastructure.Persistence.Repositories;

public sealed class DeadLetterRepository : IDeadLetterRepository
{
    private readonly CashLineErpDbContext _dbContext;

    public DeadLetterRepository(CashLineErpDbContext dbContext)
    {
        _dbContext = dbContext;
    }

    public IReadOnlyCollection<DeadLetterQueueItemView> GetDeadLetters(string? queueType = null)
    {
        var normalizedQueueType = string.IsNullOrWhiteSpace(queueType) ? null : queueType.Trim().ToUpperInvariant();
        if (normalizedQueueType is not null && normalizedQueueType != "INBOX" && normalizedQueueType != "OUTBOX")
        {
            throw new InvalidOperationException("Dead-letter queue type must be INBOX, OUTBOX, or omitted.");
        }

        var items = new List<DeadLetterQueueItemView>();

        if (normalizedQueueType is null || normalizedQueueType == "OUTBOX")
        {
            items.AddRange(_dbContext.OutboxEvents
                .AsNoTracking()
                .Where(entry => entry.StatusCode == "DEAD_LETTER")
                .Select(entry => new DeadLetterQueueItemView(
                    "OUTBOX",
                    entry.Id,
                    entry.EventNumber,
                    entry.SourceModuleCode,
                    entry.EventType,
                    entry.CorrelationKey,
                    entry.StatusCode,
                    entry.AttemptNumber,
                    entry.AvailableAtUtc,
                    entry.LastErrorText,
                    entry.CreatedAtUtc))
                .ToArray());
        }

        if (normalizedQueueType is null || normalizedQueueType == "INBOX")
        {
            items.AddRange((
                from message in _dbContext.InboxMessages.AsNoTracking()
                join endpoint in _dbContext.IntegrationEndpointRegistryEntries.AsNoTracking()
                    on message.IntegrationEndpointId equals endpoint.Id
                where message.StatusCode == "DEAD_LETTER"
                select new DeadLetterQueueItemView(
                    "INBOX",
                    message.Id,
                    message.MessageNumber,
                    endpoint.EndpointCode,
                    message.MessageType,
                    message.CorrelationKey ?? message.ExternalMessageId,
                    message.StatusCode,
                    message.AttemptNumber,
                    message.AvailableAtUtc,
                    message.LastErrorText,
                    message.CreatedAtUtc)).ToArray());
        }

        return items
            .OrderBy(item => item.QueueType)
            .ThenBy(item => item.CreatedAtUtc)
            .ThenBy(item => item.ReferenceNumber)
            .ToArray();
    }
}
