using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;

namespace DeepDrftPublic.Client.Controls;

/// <summary>
/// Share affordance for the track detail page: a popover offering a canonical-link copy
/// and an optional iframe embed snippet. Clipboard writes go through navigator.clipboard;
/// each copy shows a transient "Copied!" confirmation that resets after a short delay.
/// </summary>
public partial class SharePopover : ComponentBase, IDisposable
{
    [Parameter] public string? EntryKey { get; set; }

    [Inject] public required NavigationManager Navigation { get; set; }
    [Inject] public required IJSRuntime JS { get; set; }

    private bool _open;
    private bool _embed;
    private bool _linkCopied;
    private bool _embedCopied;

    private readonly CancellationTokenSource _cts = new();

    private bool Embed
    {
        get => _embed;
        set
        {
            _embed = value;
            if (!value) _embedCopied = false;
        }
    }

    private string TrackUrl => $"{Navigation.BaseUri}track/{EntryKey}";

    private string EmbedSnippet =>
        $"""<iframe src="{Navigation.BaseUri}FramePlayer?TrackEntryKey={EntryKey}" width="656" height="196" frameborder="0" style="border-radius:8px;" allow="autoplay"></iframe>""";

    private void Toggle() => _open = !_open;

    private void Close() => _open = false;

    private async Task CopyLink()
    {
        if (await CopyToClipboard(TrackUrl))
        {
            _linkCopied = true;
            await ResetAfterDelay(() => _linkCopied = false);
        }
    }

    private async Task CopyEmbed()
    {
        if (await CopyToClipboard(EmbedSnippet))
        {
            _embedCopied = true;
            await ResetAfterDelay(() => _embedCopied = false);
        }
    }

    private async Task<bool> CopyToClipboard(string text)
    {
        try
        {
            await JS.InvokeVoidAsync("navigator.clipboard.writeText", text);
            return true;
        }
        catch (Exception)
        {
            return false;
        }
    }

    private async Task ResetAfterDelay(Action reset)
    {
        try
        {
            await Task.Delay(1500, _cts.Token);
        }
        catch (TaskCanceledException)
        {
            return;
        }

        reset();
        StateHasChanged();
    }

    public void Dispose() => _cts.Cancel();
}
