using Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.Extensions.Toolkit;
using Olive.Klipy;
using Olive.Services;

namespace Olive.Commands;

internal sealed partial class CopyGifCommand : InvokableCommand
{
    private readonly KlipyGif _gif;
    private readonly GifCache _cache;

    public CopyGifCommand(KlipyGif gif, GifCache cache)
    {
        _gif = gif;
        _cache = cache;
        Name = "Copy GIF";
        Icon = new IconInfo("\uE8C8");
    }

    public override ICommandResult Invoke()
    {
        _ = CopyAsync();
        return CommandResult.KeepOpen();
    }

    private async Task CopyAsync()
    {
        using var cancellation = new CancellationTokenSource(TimeSpan.FromSeconds(30));
        try
        {
            ShowStatus("Downloading GIF...", MessageState.Info, 800);
            var path = await _cache.GetOrDownloadAsync(_gif, cancellation.Token).ConfigureAwait(false);
            await ClipboardService.CopyGifFileAsync(path, _gif.GifUrl, _gif.Title, cancellation.Token).ConfigureAwait(false);
            ShowStatus("GIF copied - paste with Ctrl + V", MessageState.Success, 3500);
        }
        catch (OperationCanceledException)
        {
            ShowStatus("Copy cancelled or timed out.", MessageState.Warning, 2500);
        }
        catch (Exception ex) when (ex is HttpRequestException or IOException or InvalidOperationException or UnauthorizedAccessException)
        {
            ShowStatus("Could not copy this GIF.", MessageState.Error, 3500);
        }
    }

    private static void ShowStatus(string message, MessageState state, int duration)
    {
        new ToastStatusMessage(new StatusMessage { Message = message, State = state }) { Duration = duration }.Show();
    }
}
