using Application.Abstractions.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

namespace Infrastructure.YouTube;

/// <summary>
/// YouTube Data API v3 요청에 API Key를 자동으로 추가하는 DelegatingHandler
/// DB Config에서 YouTube API Key를 조회하여 쿼리스트링에 &amp;key=xxx 추가
/// </summary>
internal sealed class YouTubeApiKeyHandler(
    IServiceProvider serviceProvider,
    ILogger<YouTubeApiKeyHandler> logger
) : DelegatingHandler
{
    private string? _cachedApiKey;
    private DateTime _cachedAt = DateTime.MinValue;
    private static readonly TimeSpan CacheDuration = TimeSpan.FromMinutes(30);

    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        var apiKey = await GetApiKeyAsync(cancellationToken);

        if (!string.IsNullOrEmpty(apiKey) && request.RequestUri is not null)
        {
            // 이미 Authorization 헤더(OAuth)가 있으면 API Key 추가 안 함
            if (request.Headers.Authorization is null)
            {
                var uriStr = request.RequestUri.ToString();
                var separator = uriStr.Contains('?') ? "&" : "?";
                request.RequestUri = new Uri($"{uriStr}{separator}key={Uri.EscapeDataString(apiKey)}");
            }
        }
        else
        {
            logger.LogWarning("[YouTube] API Key가 비어있습니다. DB Config > External > YouTubeApiKeyEnc를 확인하세요.");
        }

        return await base.SendAsync(request, cancellationToken);
    }

    private async Task<string?> GetApiKeyAsync(CancellationToken ct)
    {
        if (_cachedApiKey is not null && DateTime.UtcNow - _cachedAt < CacheDuration)
        {
            return _cachedApiKey;
        }

        try
        {
            using var scope = serviceProvider.CreateScope();
            var db = scope.ServiceProvider.GetRequiredService<IAppDbContext>();

            var config = await db.Config.AsNoTracking().FirstOrDefaultAsync(ct);
            if (config is null)
            {
                return null;
            }

            // Config.External.YouTubeApiKeyEnc에서 API Key 가져옴
            _cachedApiKey = config.External?.YouTubeApiKeyEnc;
            _cachedAt = DateTime.UtcNow;

            return _cachedApiKey;
        }
        catch (Exception ex)
        {
            logger.LogWarning(ex, "[YouTube] API Key 조회 실패");
            return _cachedApiKey; // 이전 캐시 반환
        }
    }
}