using Microsoft.AspNetCore.Mvc;

namespace DeepDrftPublic.Controllers;

/// <summary>
/// Proxies public image API calls to DeepDrftAPI so the browser never makes
/// cross-origin requests. Mirrors <see cref="TrackProxyController"/>: the WASM
/// client issues relative <c>api/image/{entryKey}</c> requests against this host,
/// which forwards them upstream. SSR prerender calls DeepDrftAPI directly via the
/// same named client — no proxy hop needed on the server side.
/// </summary>
[ApiController]
[Route("api/image")]
public class ImageProxyController : ControllerBase
{
    private readonly HttpClient _upstream;
    private readonly ILogger<ImageProxyController> _logger;

    public ImageProxyController(IHttpClientFactory httpClientFactory, ILogger<ImageProxyController> logger)
    {
        _upstream = httpClientFactory.CreateClient("DeepDrft.API");
        _logger = logger;
    }

    /// <summary>Proxies image binary streaming by vault entry key from DeepDrftAPI.</summary>
    [HttpGet("{entryKey}")]
    public async Task<ActionResult> GetImage(string entryKey, CancellationToken ct = default)
    {
        _logger.LogInformation("Proxying image {EntryKey}", entryKey);

        var path = $"api/image/{Uri.EscapeDataString(entryKey)}";

        HttpResponseMessage upstream;
        try
        {
            upstream = await _upstream.GetAsync(path, HttpCompletionOption.ResponseHeadersRead, ct);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Upstream call to DeepDrftAPI image/{EntryKey} failed", entryKey);
            return StatusCode(502, "Upstream unavailable");
        }

        if (!upstream.IsSuccessStatusCode)
        {
            upstream.Dispose();
            _logger.LogWarning("DeepDrftAPI image/{EntryKey} returned {Status}", entryKey, (int)upstream.StatusCode);
            return StatusCode((int)upstream.StatusCode);
        }

        // Do NOT dispose upstream here — File() takes ownership of the response stream
        // and disposes it after the body is sent.
        var contentType = upstream.Content.Headers.ContentType?.ToString() ?? "application/octet-stream";
        var contentLength = upstream.Content.Headers.ContentLength;

        if (contentLength.HasValue)
            Response.ContentLength = contentLength.Value;

        var stream = await upstream.Content.ReadAsStreamAsync(ct);
        HttpContext.Response.RegisterForDispose(upstream);
        return File(stream, contentType, enableRangeProcessing: false);
    }
}
