using System;
using System.Threading;
using System.Threading.Tasks;
using Jellyfin.Plugin.SRFPlay.Services.Interfaces;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Session;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

namespace Jellyfin.Plugin.SRFPlay.Services;

/// <summary>
/// Watches for livestream playback ending and immediately drops the resume point Jellyfin
/// just saved for it. Without this, every livestream a user stops watching sticks in
/// "Continue Watching" until the nightly cleanup task runs.
/// </summary>
public class PlaybackResumeGuard : IHostedService
{
    private readonly ILogger<PlaybackResumeGuard> _logger;
    private readonly ISessionManager _sessionManager;
    private readonly IResumeCleanupService _resumeCleanupService;

    /// <summary>
    /// Initializes a new instance of the <see cref="PlaybackResumeGuard"/> class.
    /// </summary>
    /// <param name="logger">The logger.</param>
    /// <param name="sessionManager">The session manager raising playback events.</param>
    /// <param name="resumeCleanupService">The resume cleanup service.</param>
    public PlaybackResumeGuard(
        ILogger<PlaybackResumeGuard> logger,
        ISessionManager sessionManager,
        IResumeCleanupService resumeCleanupService)
    {
        _logger = logger;
        _sessionManager = sessionManager;
        _resumeCleanupService = resumeCleanupService;
    }

    /// <inheritdoc />
    public Task StartAsync(CancellationToken cancellationToken)
    {
        _sessionManager.PlaybackStopped += OnPlaybackStopped;
        _logger.LogDebug("PlaybackResumeGuard attached to session manager");
        return Task.CompletedTask;
    }

    /// <inheritdoc />
    public Task StopAsync(CancellationToken cancellationToken)
    {
        _sessionManager.PlaybackStopped -= OnPlaybackStopped;
        return Task.CompletedTask;
    }

    private void OnPlaybackStopped(object? sender, PlaybackStopEventArgs e)
    {
        // Jellyfin saves the resume point before raising this event, so clearing it here wins.
        if (e?.Item == null || e.Users == null || e.Users.Count == 0)
        {
            return;
        }

        try
        {
            var cleared = _resumeCleanupService.ClearLiveStreamResumePoint(e.Item, e.Users);
            if (cleared > 0)
            {
                _logger.LogDebug(
                    "Dropped {Count} resume point(s) for finished livestream '{Name}'",
                    cleared,
                    e.Item.Name);
            }
        }
        catch (Exception ex)
        {
            // Never let a cleanup failure escape into Jellyfin's playback event pipeline.
            _logger.LogError(ex, "Error clearing livestream resume point for '{Name}'", e.Item.Name);
        }
    }
}
