using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;

namespace Jellyfin.Plugin.SRFPlay.Services.Interfaces;

/// <summary>
/// Interface for proxying SRF Play streams and managing authentication.
/// </summary>
public interface IStreamProxyService
{
    /// <summary>
    /// Registers a stream for deferred authentication (authenticates on first playback request).
    /// Use this when browsing to avoid wasting 30-second tokens before the user clicks play.
    /// </summary>
    /// <param name="itemId">The item ID.</param>
    /// <param name="unauthenticatedUrl">The unauthenticated stream URL.</param>
    /// <param name="urn">The SRF URN for this content.</param>
    /// <param name="isLiveStream">Whether this is a livestream.</param>
    void RegisterStreamDeferred(string itemId, string unauthenticatedUrl, string? urn = null, bool isLiveStream = false);

    /// <summary>
    /// Gets stream metadata for an item (URN and isLiveStream flag).
    /// </summary>
    /// <param name="itemId">The item ID.</param>
    /// <returns>A tuple of (URN, IsLiveStream), or null if not found.</returns>
    (string? Urn, bool IsLiveStream)? GetStreamMetadata(string itemId);

    /// <summary>
    /// Gets the authenticated URL for an item.
    /// </summary>
    /// <param name="itemId">The item ID.</param>
    /// <param name="cancellationToken">Cancellation token.</param>
    /// <returns>The authenticated URL, or null if not found or expired.</returns>
    Task<string?> GetAuthenticatedUrlAsync(string itemId, CancellationToken cancellationToken = default);

    /// <summary>
    /// Fetches and rewrites an HLS manifest to use proxy URLs.
    /// </summary>
    /// <param name="itemId">The item ID.</param>
    /// <param name="baseProxyUrl">The base proxy URL.</param>
    /// <param name="cancellationToken">Cancellation token.</param>
    /// <returns>The rewritten manifest content.</returns>
    Task<string?> GetRewrittenManifestAsync(string itemId, string baseProxyUrl, CancellationToken cancellationToken = default);

    /// <summary>
    /// Fetches a segment from the original source.
    /// </summary>
    /// <param name="itemId">The item ID.</param>
    /// <param name="segmentPath">The segment path.</param>
    /// <param name="queryString">The original query string from the request (preserves segment-specific parameters like timestamps).</param>
    /// <param name="cancellationToken">Cancellation token.</param>
    /// <returns>The segment content as bytes.</returns>
    Task<byte[]?> GetSegmentAsync(string itemId, string segmentPath, string? queryString = null, CancellationToken cancellationToken = default);

    /// <summary>
    /// Fetches a segment from the original source as a streaming response.
    /// Returns the HttpResponseMessage for streaming directly to the client, reducing TTFB.
    /// The caller is responsible for disposing the response.
    /// </summary>
    /// <param name="itemId">The item ID.</param>
    /// <param name="segmentPath">The segment path.</param>
    /// <param name="queryString">The original query string from the request.</param>
    /// <param name="cancellationToken">Cancellation token.</param>
    /// <returns>The HTTP response for streaming, or null if not found.</returns>
    Task<HttpResponseMessage?> GetSegmentStreamAsync(string itemId, string segmentPath, string? queryString = null, CancellationToken cancellationToken = default);

    /// <summary>
    /// Rewrites URLs in a variant (sub) manifest to point to the proxy.
    /// </summary>
    /// <param name="manifestContent">The variant manifest content.</param>
    /// <param name="baseProxyUrl">The base proxy URL (without query params).</param>
    /// <param name="queryParams">Query parameters to append to rewritten URLs (e.g., "?token=abc").</param>
    /// <param name="isLiveStream">Whether this is a livestream; if so an EXT-X-START offset is injected.</param>
    /// <returns>The rewritten manifest content.</returns>
    string RewriteVariantManifestUrls(string manifestContent, string baseProxyUrl, string queryParams, bool isLiveStream = false);

    /// <summary>
    /// Cleans up old and expired stream mappings.
    /// </summary>
    void CleanupOldMappings();
}
