@namespace Lumeo
@inject Lumeo.Services.IComponentInteropService Interop

<button @ref="_el" type="@TypeAttr" class="@CssClass" disabled="@(IsLoading || Disabled)" @attributes="AdditionalAttributes" @onclick="OnClick" @onclick:stopPropagation="StopPropagation" @onclick:preventDefault="PreventDefault">
    @if (IsLoading)
    {
        <Spinner Class="h-4 w-4" />
        @if (LoadingText != null)
        {
            <span>@LoadingText</span>
        }
        else
        {
            @ChildContent
        }
        @if (RightIcon != null)
        {
            @RightIcon
        }
    }
    else
    {
        @if (LeftIcon != null)
        {
            @LeftIcon
        }
        @ChildContent
        @if (RightIcon != null)
        {
            @RightIcon
        }
    }
</button>

@code {
    [Parameter] public RenderFragment? ChildContent { get; set; }
    [Parameter] public RenderFragment? LeftIcon { get; set; }
    [Parameter] public RenderFragment? RightIcon { get; set; }
    [Parameter] public ButtonVariant Variant { get; set; } = ButtonVariant.Default;
    [Parameter] public ButtonSize Size { get; set; } = ButtonSize.Default;
    [Parameter] public bool FullWidth { get; set; }
    [Parameter] public string? Class { get; set; }
    [Parameter] public EventCallback<Microsoft.AspNetCore.Components.Web.MouseEventArgs> OnClick { get; set; }
    [Parameter] public bool Disabled { get; set; }
    [Parameter] public bool IsLoading { get; set; }
    [Parameter] public string? LoadingText { get; set; }

    /// <summary>HTML button type. Defaults to <see cref="ButtonType.Button"/>
    /// — explicitly NOT submit. The HTML spec says &lt;button&gt; inside
    /// &lt;form&gt; defaults to <c>type="submit"</c>, which would submit the
    /// form on every click. Lumeo defaults to a regular button so Buttons
    /// don't silently submit EditForm; opt in via <c>Type="Submit"</c>.</summary>
    [Parameter] public ButtonType Type { get; set; } = ButtonType.Button;

    /// <summary>Stop click propagation to ancestors. Use this instead of
    /// the Razor directive <c>@@onclick:stopPropagation</c> on a Lumeo
    /// component — that directive creates an <c>onclick</c> parameter
    /// that case-insensitively collides with the <c>OnClick</c>
    /// parameter, producing a compile error. The directive only works
    /// natively on HTML elements; this parameter is the equivalent for
    /// the &lt;button&gt; element underneath.</summary>
    [Parameter] public bool StopPropagation { get; set; }

    /// <summary>Prevent the default click action on the underlying
    /// &lt;button&gt; element. Same rationale as <see cref="StopPropagation"/>
    /// — Razor's <c>@@onclick:preventDefault</c> directive collides
    /// case-insensitively with the <c>OnClick</c> parameter on
    /// components.</summary>
    [Parameter] public bool PreventDefault { get; set; }

    /// <summary>
    /// Visual feedback when the button is pressed down. Default is <see cref="ButtonPressEffect.None"/>
    /// (no press animation — original behaviour).
    /// </summary>
    [Parameter] public ButtonPressEffect PressEffect { get; set; } = ButtonPressEffect.None;

    [Parameter(CaptureUnmatchedValues = true)] public Dictionary<string, object>? AdditionalAttributes { get; set; }

    private Microsoft.AspNetCore.Components.ElementReference _el;

    private string CssClass => string.Join(" ", new[] { VariantClasses, SizeClasses, BaseClasses, PressEffectClass, "cursor-pointer disabled:cursor-not-allowed", IsLoading ? "pointer-events-none opacity-70" : null, FullWidth ? "w-full" : null, Class }.Where(s => !string.IsNullOrWhiteSpace(s)));

    private const string BaseClasses = "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-[1.5px] focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50";

    private string? PressEffectClass => PressEffect switch
    {
        ButtonPressEffect.Scale => "lumeo-press-scale",
        ButtonPressEffect.Brightness => "lumeo-press-brightness",
        ButtonPressEffect.Ripple => "lumeo-press-ripple",
        _ => null
    };

    private string VariantClasses => Variant switch
    {
        ButtonVariant.Default => "bg-primary text-primary-foreground shadow hover:bg-primary/90",
        ButtonVariant.Destructive => "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
        ButtonVariant.Outline => "border border-input bg-background hover:bg-accent hover:text-accent-foreground",
        ButtonVariant.Secondary => "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
        ButtonVariant.Ghost => "hover:bg-accent hover:text-accent-foreground",
        ButtonVariant.Link => "text-primary underline-offset-4 hover:underline",
        _ => ""
    };

    private string SizeClasses => Size switch
    {
        ButtonSize.Default => "h-9 px-4 py-2",
        ButtonSize.Sm => "h-8 rounded-md px-3 text-xs",
        ButtonSize.Lg => "h-10 rounded-md px-8",
        ButtonSize.Icon => "h-9 w-9",
        _ => ""
    };

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender && PressEffect == ButtonPressEffect.Ripple)
        {
            try
            {
                await Interop.RippleAttachAsync(_el);
            }
            catch (Microsoft.JSInterop.JSDisconnectedException) { }
        }
    }

    public enum ButtonVariant { Default, Destructive, Outline, Secondary, Ghost, Link }
    public enum ButtonSize { Default, Sm, Lg, Icon }
    public enum ButtonType { Button, Submit, Reset }

    private string TypeAttr => Type switch
    {
        ButtonType.Submit => "submit",
        ButtonType.Reset => "reset",
        _ => "button",
    };

    /// <summary>Visual press feedback style for <see cref="Button"/>.</summary>
    public enum ButtonPressEffect
    {
        /// <summary>No press animation (default).</summary>
        None,
        /// <summary>Button slightly scales down (~97%) while pressed.</summary>
        Scale,
        /// <summary>Button darkens/brightens slightly while pressed.</summary>
        Brightness,
        /// <summary>Click ripples outward from the cursor point (JS-interop, uses CSS mask).</summary>
        Ripple
    }
}
