using FrameProcessor.Configuration;
using FrameProcessor.Domain;
using FrameProcessor.ImagePipeline;
using FrameProcessor.Mqtt;
using FrameProcessor.Storage;
using Microsoft.AspNetCore.Mvc;

namespace FrameProcessor.Controllers;

[ApiController]
[Route("api/frames")]
public sealed class FramesController : ControllerBase
{
    private readonly FramesRegistry _frames;
    private readonly IImagePipeline _pipeline;
    private readonly ImageStore _store;
    private readonly MqttPublisher _mqtt;

    public FramesController(FramesRegistry frames, IImagePipeline pipeline, ImageStore store, MqttPublisher mqtt)
    {
        _frames = frames;
        _pipeline = pipeline;
        _store = store;
        _mqtt = mqtt;
    }

    [HttpPost("{name}/image")]
    public async Task<IActionResult> UploadImage(string name, CancellationToken cancellationToken)
    {
        if (!FrameName.TryParse(name, out var frameName) || !_frames.TryGetByName(frameName, out var frame))
        {
            return NotFound();
        }

        var file = Request.Form.Files.GetFile("image");
        if (file is null || file.Length == 0)
        {
            return BadRequest(new { error = "Missing 'image' file part." });
        }

        byte[] pngBytes;
        await using (var stream = file.OpenReadStream())
        {
            pngBytes = _pipeline.Process(stream, frame);
        }

        await _store.WriteAsync(frame.Mac, pngBytes, cancellationToken).ConfigureAwait(false);

        var publishResult = await _mqtt.PublishAsync(frame.Mac, cancellationToken).ConfigureAwait(false);

        return Ok(new
        {
            frame = frame.Name.Value,
            mac = frame.Mac.ToString(),
            url = $"/i/{frame.Mac}.png",
            processedAt = DateTimeOffset.UtcNow,
            mqttPublished = publishResult == PublishResult.Success,
        });
    }
}
