@inject IJSRuntime JS

<section id="@ComputedId" data-toc-entry data-toc-title="@Title" class="scroll-mt-24 rounded-[var(--radius-xl)] border border-border bg-card @(OverflowVisible ? "overflow-visible" : "overflow-hidden")">
    @* Header bar with title and tab switcher *@
    <Flex Align="center" Justify="between" Class="border-b border-border px-4 py-3 bg-muted/20">
        <Flex Align="center" Gap="1" Class="rounded-[var(--radius)] border border-border bg-background p-0.5">
            <button class="@TabButtonClass(true)" @onclick="ShowPreview">
                <DynamicIcon Name="Eye" Class="h-3.5 w-3.5 mr-1.5" />
                Preview
            </button>
            <button class="@TabButtonClass(false)" @onclick="ShowCode">
                <DynamicIcon Name="Code" Class="h-3.5 w-3.5 mr-1.5" />
                Code
            </button>
        </Flex>
        <Flex Align="center" Gap="2">
            @if (Title != null)
            {
                <Lumeo.Text As="span" Size="xs" Color="muted" Weight="medium" Class="hidden sm:inline">@Title</Lumeo.Text>
            }
        </Flex>
    </Flex>

    @* Optional viewport toggle — opt-in via ShowViewportToggle. Lets demos preview
       inside a phone-width frame so the docs honestly show what wide-min-width blocks
       look like on small screens (instead of just horizontally scrolling on phones). *@
    @if (ShowViewportToggle && _activeTab == Tab.Preview)
    {
        <Flex Align="center" Justify="end" Class="border-b border-border/60 px-4 py-2 bg-muted/10">
            <Flex Align="center" Gap="1" Class="rounded-[var(--radius)] border border-border bg-background p-0.5">
                <button type="button" class="@ViewportButtonClass(Viewport.Desktop)" @onclick="() => SetViewport(Viewport.Desktop)" aria-pressed="@(_viewport == Viewport.Desktop)">
                    <DynamicIcon Name="Monitor" Class="h-3.5 w-3.5 mr-1.5" />
                    Desktop
                </button>
                <button type="button" class="@ViewportButtonClass(Viewport.Mobile)" @onclick="() => SetViewport(Viewport.Mobile)" aria-pressed="@(_viewport == Viewport.Mobile)">
                    <DynamicIcon Name="Smartphone" Class="h-3.5 w-3.5 mr-1.5" />
                    Mobile
                </button>
            </Flex>
        </Flex>
    }

    @* Preview panel *@
    @if (_activeTab == Tab.Preview)
    {
        <div class="@PreviewContainerClass">
            @if (ShowViewportToggle && _viewport == Viewport.Mobile)
            {
                <div class="max-w-[420px] w-full mx-auto rounded-[var(--radius-lg)] border border-border/60 bg-background shadow-sm overflow-x-auto">
                    <div class="px-2 py-3">
                        @ChildContent
                    </div>
                </div>
            }
            else
            {
                @ChildContent
            }
        </div>
    }

    @* Code panel *@
    @if (_activeTab == Tab.Code && Code != null)
    {
        <div class="relative">
            <div class="code-block !rounded-none !border-0 max-h-[420px] overflow-auto">@Code</div>
        </div>
    }

    @* Footer bar *@
    <Flex Align="center" Justify="between" Class="border-t border-border px-4 py-2.5 bg-muted/20">
        @if (Description != null)
        {
            <Lumeo.Text Size="xs" Color="muted">@Description</Lumeo.Text>
        }
        else
        {
            <Lumeo.Text As="span"></Lumeo.Text>
        }
        <Flex Align="center" Gap="1.5">
            @if (Code != null)
            {
                <Button Variant="Button.ButtonVariant.Ghost" Class="inline-flex items-center gap-1.5 rounded-[var(--radius)] px-2.5 py-1.5 text-xs font-medium text-muted-foreground hover:text-foreground hover:bg-accent transition-colors"
                        OnClick="CopyCode"
                        title="Copy code">
                    @if (_copied)
                    {
                        <DynamicIcon Name="Check" Class="h-3.5 w-3.5 text-primary" />
                        <Lumeo.Text As="span" Color="primary">Copied</Lumeo.Text>
                    }
                    else
                    {
                        <DynamicIcon Name="Clipboard" Class="h-3.5 w-3.5" />
                        <Lumeo.Text As="span">Copy</Lumeo.Text>
                    }
                </Button>
                <Button Variant="Button.ButtonVariant.Ghost" Class="inline-flex items-center gap-1.5 rounded-[var(--radius)] px-2.5 py-1.5 text-xs font-medium text-muted-foreground hover:text-foreground hover:bg-accent transition-colors"
                        OnClick="ToggleCode"
                        title="View source">
                    <DynamicIcon Name="Code" Class="h-3.5 w-3.5" />
                    <Lumeo.Text As="span">@(_activeTab == Tab.Code ? "Preview" : "Code")</Lumeo.Text>
                </Button>
            }
        </Flex>
    </Flex>
</section>

@code {
    [Parameter] public RenderFragment? ChildContent { get; set; }
    [Parameter] public string? Title { get; set; }
    [Parameter] public string? Code { get; set; }
    [Parameter] public string? Description { get; set; }
    [Parameter] public bool OverflowVisible { get; set; }
    [Parameter] public string? Id { get; set; }

    /// <summary>
    /// When true, renders a Desktop / Mobile viewport toggle above the preview.
    /// When set to Mobile, the demo content is wrapped in a 420 px-wide phone frame —
    /// any inner <c>min-w-[…]</c> remains, so the preview honestly shows the
    /// horizontal scroll the user would experience on a real phone.
    /// </summary>
    [Parameter] public bool ShowViewportToggle { get; set; }

    private string? ComputedId => Id ?? (string.IsNullOrWhiteSpace(Title) ? null : Slugify(Title!));

    private static string Slugify(string input)
    {
        var sb = new System.Text.StringBuilder();
        bool lastWasDash = false;
        foreach (var ch in input.ToLowerInvariant())
        {
            if (char.IsLetterOrDigit(ch)) { sb.Append(ch); lastWasDash = false; }
            else if (!lastWasDash && sb.Length > 0) { sb.Append('-'); lastWasDash = true; }
        }
        var s = sb.ToString().TrimEnd('-');
        return string.IsNullOrEmpty(s) ? "demo" : s;
    }

    private string PreviewContainerClass => OverflowVisible
        ? "min-h-[160px] p-6 sm:p-8 bg-muted/20 overflow-visible flex items-center justify-center"
        : "min-h-[160px] p-6 sm:p-8 bg-muted/20 overflow-x-auto flex items-center justify-center";

    private enum Tab { Preview, Code }
    private Tab _activeTab = Tab.Preview;
    private bool _copied;

    private enum Viewport { Desktop, Mobile }
    private Viewport _viewport = Viewport.Desktop;

    private void SetViewport(Viewport v) => _viewport = v;

    private string ViewportButtonClass(Viewport v)
    {
        var active = _viewport == v;
        return active
            ? "inline-flex items-center rounded px-2.5 py-1 text-xs font-medium bg-background shadow-sm text-foreground transition-all"
            : "inline-flex items-center rounded px-2.5 py-1 text-xs font-medium text-muted-foreground hover:text-foreground transition-all";
    }

    private string TabButtonClass(bool isPreview)
    {
        var active = (isPreview && _activeTab == Tab.Preview) || (!isPreview && _activeTab == Tab.Code);
        return active
            ? "inline-flex items-center rounded px-3 py-1 text-xs font-medium bg-background shadow-sm text-foreground transition-all"
            : "inline-flex items-center rounded px-3 py-1 text-xs font-medium text-muted-foreground hover:text-foreground transition-all";
    }

    private void ShowPreview() => _activeTab = Tab.Preview;
    private void ShowCode() => _activeTab = Tab.Code;
    private void ToggleCode() => _activeTab = _activeTab == Tab.Code ? Tab.Preview : Tab.Code;

    private async Task CopyCode()
    {
        if (Code == null) return;
        try { await JS.InvokeVoidAsync("navigator.clipboard.writeText", Code); } catch (JSException) { /* clipboard API may be unavailable */ }
        _copied = true;
        StateHasChanged();
        await Task.Delay(2000);
        _copied = false;
        StateHasChanged();
    }
}
