using DeepDrftModels.Enums;
using DeepDrftPublic.Client.Common;
using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;

namespace DeepDrftPublic.Client.Controls;

/// <summary>
/// Share affordance with two modes from one source of clipboard/popover-chrome logic
/// (Phase 11 §3b). Track mode (<see cref="EntryKey"/> set) offers a canonical-link copy plus an
/// optional iframe embed snippet. Release mode (<see cref="ReleaseEntryKey"/> set) is copy-link-only —
/// it copies the absolute form of the release's canonical detail URL and hides the embed
/// affordance, since a release page is not a single-track embed. 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
{
    /// <summary>Track mode: the vault entry key of the track to share. Mutually exclusive with the release target.</summary>
    [Parameter] public string? EntryKey { get; set; }

    /// <summary>Release mode: the release's opaque public EntryKey to share. When set (with <see cref="ReleaseMedium"/>), the popover shares the release detail URL and omits the embed option.</summary>
    [Parameter] public string? ReleaseEntryKey { get; set; }

    /// <summary>Release mode: the medium of the release, used to resolve its canonical detail route.</summary>
    [Parameter] public ReleaseMedium ReleaseMedium { get; set; }

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

    private bool IsReleaseMode => ReleaseEntryKey is not null;

    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;
        }
    }

    // The URL "Copy link" places on the clipboard. Release mode resolves the canonical detail
    // route (which carries a leading slash) and composes it against BaseUri (which carries a
    // trailing slash) — trim one to avoid a doubled separator.
    private string LinkUrl => IsReleaseMode
        ? $"{Navigation.BaseUri.TrimEnd('/')}{ReleaseRoutes.DetailHref(ReleaseEntryKey!, ReleaseMedium)}"
        : TrackUrl;

    private string TrackUrl => $"{Navigation.BaseUri}tracks/{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(LinkUrl))
        {
            _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();
}
