using System.Threading;
using System.Threading.Tasks;
using Jellyfin.Plugin.SRFPlay.Api;
using Jellyfin.Plugin.SRFPlay.Api.Models;
using Jellyfin.Plugin.SRFPlay.Services.Interfaces;
using Microsoft.Extensions.Logging;

namespace Jellyfin.Plugin.SRFPlay.Services;

/// <summary>
/// Service for fetching media composition with caching support.
/// This consolidates the cache-check → API-fetch → cache-store pattern.
/// </summary>
public class MediaCompositionFetcher : IMediaCompositionFetcher
{
    private readonly ILogger<MediaCompositionFetcher> _logger;
    private readonly IMetadataCache _metadataCache;
    private readonly ISRFApiClientFactory _apiClientFactory;

    /// <summary>
    /// Initializes a new instance of the <see cref="MediaCompositionFetcher"/> class.
    /// </summary>
    /// <param name="logger">The logger.</param>
    /// <param name="metadataCache">The metadata cache.</param>
    /// <param name="apiClientFactory">The API client factory.</param>
    public MediaCompositionFetcher(
        ILogger<MediaCompositionFetcher> logger,
        IMetadataCache metadataCache,
        ISRFApiClientFactory apiClientFactory)
    {
        _logger = logger;
        _metadataCache = metadataCache;
        _apiClientFactory = apiClientFactory;
    }

    /// <inheritdoc />
    public async Task<MediaComposition?> GetMediaCompositionAsync(
        string urn,
        CancellationToken cancellationToken,
        int? cacheDurationOverride = null)
    {
        if (string.IsNullOrEmpty(urn))
        {
            _logger.LogDebug("GetMediaCompositionAsync called with null/empty URN");
            return null;
        }

        var config = Plugin.Instance?.Configuration;
        if (config == null)
        {
            _logger.LogWarning("Plugin configuration is null, cannot fetch media composition");
            return null;
        }

        var cacheDuration = cacheDurationOverride ?? config.CacheDurationMinutes;

        // Try cache first
        var mediaComposition = _metadataCache.GetMediaComposition(urn, cacheDuration);
        if (mediaComposition != null)
        {
            _logger.LogDebug("Cache hit for URN: {Urn}", urn);
            return mediaComposition;
        }

        // Fetch from API
        _logger.LogDebug("Cache miss for URN: {Urn}, fetching from API", urn);
        using var apiClient = _apiClientFactory.CreateClient();
        mediaComposition = await apiClient.GetMediaCompositionByUrnAsync(urn, cancellationToken).ConfigureAwait(false);

        if (mediaComposition != null)
        {
            _metadataCache.SetMediaComposition(urn, mediaComposition);
            _logger.LogDebug("Cached media composition for URN: {Urn}", urn);
        }
        else
        {
            _logger.LogWarning("Failed to fetch media composition for URN: {Urn}", urn);
        }

        return mediaComposition;
    }
}
