using Modules.Library.Domain.Entities;
using MediatR;
using Modules.Media.Api.Commands;

namespace Modules.Library.Application.Services;

public class MediaInfoService(IMediator mediator, IHttpClientFactory httpClientFactory)
{
    private const string _busketName = "my-bookmark.library";
    public async Task<(string ObjectId, string ContentType)> Add(CreateModel model, bool isPreview, CancellationToken cancellationToken)
    {
        //if (!user.CanAddMediaInfo()) throw new Exception("AccessDenied");
        if (model.Data == null && string.IsNullOrWhiteSpace(model.Url))
        {
            throw new Exception("No Data and url inside MediaInfo");
        }

        var command = new AddObjectCommand
        {
            ObjectName = !string.IsNullOrWhiteSpace(model.ObjectName) ? model.ObjectName : GetObjectName(model.Id, isPreview),
            BusketName = _busketName,
            ObjectPrefix = GetPrefix(isPreview),
        };
        string? objectId = null;

        if (model.Data != null)
        {
            command.ContentType = model.ContentType ?? "application/octet-stream";
            command.Data = model.Data;
            //command.ObjectExtension = relatedContentItem.ex, //get extension from mime-type
            command.ObjectExtension = "png";
            objectId = await mediator.Send(command, cancellationToken) ?? throw new Exception("Preview is not set");
        }
        else
        {
            var client = httpClientFactory.CreateClient();
            var response = await client.GetAsync(model.Url);
            response.EnsureSuccessStatusCode();
            command.ContentType = response.Content.Headers.GetValues("Content-Type").First();
            using var responseStream = await response.Content.ReadAsStreamAsync(cancellationToken);
            command.Data = responseStream;
            //command.ObjectExtension = relatedContentItem.ex, //get extension from mime-type
            command.ObjectExtension = "png";
            objectId = await mediator.Send(command, cancellationToken) ?? throw new Exception("Preview is not set");
        }

        return (objectId, command.ContentType);
    }

    private static string? GetObjectName(Guid? id, bool isPreview)
    {
        if (!isPreview || !id.HasValue) return null;
        return string.Concat(GetPrefix(isPreview), "_", id);
    }

    private static string GetPrefix(bool isPreview) => isPreview ? "preview" : "related_content";

    public async Task<bool> Remove(string objectId, bool isPreview, CancellationToken cancellationToken)
    //public async Task<bool> Remove(IUser user, string objectId, bool isPreview, CancellationToken cancellationToken)
    {
        //if (!user.CanRemoveMediaInfo()) throw new Exception("AccessDenied");
        return await mediator.Send(new DeleteObjectCommand
        {
            BusketName = _busketName,
            ObjectName = objectId,
            UseVersions = isPreview,
        }, cancellationToken);
    }

    public class CreateModel
    {
        public Guid? Id { get; set; }
        public string? ObjectName { get; set; }
        public Stream? Data { get; set; }
        public string? Url { get; set; }
        public string? ContentType { get; set; }
        public MediaInfoType Type { get; set; }
    }
}