using System;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Predictalytics.Application.Interfaces;

namespace Predictalytics.Infrastructure.Services;

public static class EgressRequestOptions
{
    public static readonly HttpRequestOptionsKey<string> ChannelIdKey = new("EgressChannelId");
}

public class EgressPoolHandler : DelegatingHandler
{
    private readonly IEgressPoolService _egressPool;
    private readonly ILogger<EgressPoolHandler> _logger;

    public EgressPoolHandler(IEgressPoolService egressPool, ILogger<EgressPoolHandler> logger)
    {
        _egressPool = egressPool;
        _logger = logger;
    }

    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        string? channelId = null;
        if (request.Options.TryGetValue(EgressRequestOptions.ChannelIdKey, out var cid))
        {
            channelId = cid;
        }

        if (string.IsNullOrEmpty(channelId))
        {
            _logger.LogDebug("🔌 Routing request to {Host} using default channel (fallback)", request.RequestUri?.Host);
            return await base.SendAsync(request, cancellationToken);
        }

        var invoker = _egressPool.GetInvoker(channelId);
        if (invoker == null)
        {
            _logger.LogWarning("🔌 Egress channel '{Id}' not found. Falling back to default channel.", channelId);
            return await base.SendAsync(request, cancellationToken);
        }

        _logger.LogDebug("🔌 Routing request to {Host} using channel '{ChannelId}'", request.RequestUri?.Host, channelId);

        try
        {
            var response = await invoker.SendAsync(request, cancellationToken);
            _egressPool.ReportSuccess(channelId);
            return response;
        }
        catch (Exception ex)
        {
            _egressPool.ReportFailure(channelId, ex);
            throw;
        }
    }
}
