using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Jellyfin.Plugin.SRFPlay.Services.Interfaces;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using Microsoft.Extensions.Logging;

namespace Jellyfin.Plugin.SRFPlay.Services;

/// <summary>
/// Service for managing content expiration.
/// </summary>
public class ContentExpirationService : IContentExpirationService
{
    private readonly ILogger<ContentExpirationService> _logger;
    private readonly ILibraryManager _libraryManager;
    private readonly IStreamUrlResolver _streamResolver;
    private readonly IMediaCompositionFetcher _compositionFetcher;

    /// <summary>
    /// Initializes a new instance of the <see cref="ContentExpirationService"/> class.
    /// </summary>
    /// <param name="loggerFactory">The logger factory.</param>
    /// <param name="libraryManager">The library manager.</param>
    /// <param name="streamResolver">The stream URL resolver.</param>
    /// <param name="compositionFetcher">The media composition fetcher.</param>
    public ContentExpirationService(
        ILoggerFactory loggerFactory,
        ILibraryManager libraryManager,
        IStreamUrlResolver streamResolver,
        IMediaCompositionFetcher compositionFetcher)
    {
        _logger = loggerFactory.CreateLogger<ContentExpirationService>();
        _libraryManager = libraryManager;
        _streamResolver = streamResolver;
        _compositionFetcher = compositionFetcher;
    }

    /// <summary>
    /// Checks for expired content and removes it from the library.
    /// </summary>
    /// <param name="cancellationToken">The cancellation token.</param>
    /// <returns>The number of items removed.</returns>
    public async Task<int> CheckAndRemoveExpiredContentAsync(CancellationToken cancellationToken)
    {
        _logger.LogInformation("Starting content expiration check");
        var removedCount = 0;

        try
        {
            // Get all items with SRF provider ID
            var query = new InternalItemsQuery
            {
                HasAnyProviderId = new Dictionary<string, string> { { "SRF", string.Empty } },
                IsVirtualItem = false
            };

            var items = _libraryManager.GetItemList(query);
            _logger.LogDebug("Found {Count} SRF items to check for expiration", items.Count);

            foreach (var item in items)
            {
                if (cancellationToken.IsCancellationRequested)
                {
                    break;
                }

                try
                {
                    if (await IsItemExpiredAsync(item, cancellationToken).ConfigureAwait(false))
                    {
                        _logger.LogInformation("Removing expired item: {Name} (URN: {Urn})", item.Name, item.ProviderIds.GetValueOrDefault("SRF"));

                        // Delete the item from library
                        _libraryManager.DeleteItem(
                            item,
                            new DeleteOptions
                            {
                                DeleteFileLocation = false
                            },
                            false);

                        removedCount++;
                    }
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, "Error checking expiration for item: {Name}", item.Name);
                }
            }

            _logger.LogInformation("Content expiration check completed. Removed {Count} expired items", removedCount);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error during content expiration check");
        }

        return removedCount;
    }

    /// <summary>
    /// Checks if an item is expired.
    /// </summary>
    /// <param name="item">The item to check.</param>
    /// <param name="cancellationToken">The cancellation token.</param>
    /// <returns>True if the item is expired.</returns>
    private async Task<bool> IsItemExpiredAsync(BaseItem item, CancellationToken cancellationToken)
    {
        var urn = item.ProviderIds.GetValueOrDefault("SRF");
        if (string.IsNullOrEmpty(urn))
        {
            return false;
        }

        var mediaComposition = await _compositionFetcher.GetMediaCompositionAsync(urn, cancellationToken).ConfigureAwait(false);

        if (mediaComposition?.HasChapters != true)
        {
            // Don't treat API failures as expired - the content may still be available
            // and a transient error (network issue, 403, API outage) shouldn't delete library items
            _logger.LogWarning("Could not fetch media composition for URN: {Urn}, skipping (not treating as expired)", urn);
            return false;
        }

        var chapter = mediaComposition.ChapterList[0];
        var isExpired = _streamResolver.IsContentExpired(chapter);

        if (isExpired)
        {
            _logger.LogDebug("Item {Name} is expired (ValidTo: {ValidTo})", item.Name, chapter.ValidTo);
        }

        return isExpired;
    }
}
