@namespace Lumeo

@if (Label is not null && !InsideFormField)
{
    <label class="block text-sm font-medium text-foreground mb-1.5">
        @Label
        @if (Required)
        {
            <span class="text-destructive ml-0.5">*</span>
        }
    </label>
}

<div class="@CssClass" @attributes="AdditionalAttributes">
    @if (_editing && !Disabled)
    {
        <div class="flex items-start gap-2 w-full">
            <div class="flex-1 min-w-0">
                @if (EditMode == InplaceEditMode.Textarea)
                {
                    <textarea class="@EditInputClass"
                              rows="3"
                              value="@_editValue"
                              name="@(Name ?? FormField?.Name)"
                              aria-required="@(Required ? "true" : "false")"
                              aria-invalid="@(EffectiveInvalid ? "true" : "false")"
                              @oninput="OnInput"
                              @onkeydown="OnKeyDown"
                              @onblur="OnBlur" />
                }
                else if (EditMode == InplaceEditMode.Select && SelectOptions is not null)
                {
                    <select class="w-full rounded border border-border bg-background px-2 py-1 text-sm focus:outline-none focus:ring-1 focus:ring-ring"
                            value="@_editValue"
                            name="@(Name ?? FormField?.Name)"
                            aria-required="@(Required ? "true" : "false")"
                            aria-invalid="@(EffectiveInvalid ? "true" : "false")"
                            @onchange="OnSelectChange"
                            @onblur="OnBlur">
                        @foreach (var option in SelectOptions)
                        {
                            <option value="@option">@option</option>
                        }
                    </select>
                }
                else
                {
                    <input type="text"
                           class="@EditInputClass"
                           value="@_editValue"
                           name="@(Name ?? FormField?.Name)"
                           aria-required="@(Required ? "true" : "false")"
                           aria-invalid="@(EffectiveInvalid ? "true" : "false")"
                           @oninput="OnInput"
                           @onkeydown="OnKeyDown"
                           @onblur="OnBlur" />
                }
            </div>

            @if (ShowButtons)
            {
                <div class="flex gap-1 shrink-0">
                    <button type="button"
                            class="inline-flex items-center justify-center rounded p-1 text-xs bg-primary text-primary-foreground hover:bg-primary/90 transition-colors focus-visible:outline-none focus-visible:ring-[1.5px] focus-visible:ring-ring focus-visible:ring-offset-1"
                            @onclick="Save" @onclick:stopPropagation="true">
                        <Blazicon Svg="Lucide.Check" class="h-3 w-3" />
                    </button>
                    <button type="button"
                            class="inline-flex items-center justify-center rounded p-1 text-xs bg-muted text-muted-foreground hover:bg-muted/70 transition-colors focus-visible:outline-none focus-visible:ring-[1.5px] focus-visible:ring-ring focus-visible:ring-offset-1"
                            @onclick="Cancel" @onclick:stopPropagation="true">
                        <Blazicon Svg="Lucide.X" class="h-3 w-3" />
                    </button>
                </div>
            }
        </div>
    }
    else
    {
        <div class="@DisplayClass" @onclick="StartEditing" aria-required="@(Required ? "true" : "false")" aria-invalid="@(EffectiveInvalid ? "true" : "false")">
            <div class="flex-1 min-w-0">
                @if (ChildContent is not null)
                {
                    @ChildContent
                }
                else if (!string.IsNullOrEmpty(Value))
                {
                    <span class="text-sm">@Value</span>
                }
                else if (!string.IsNullOrEmpty(Placeholder))
                {
                    <span class="text-sm text-muted-foreground/60 italic">@Placeholder</span>
                }
            </div>
            @if (!Disabled)
            {
                <span class="ml-2 shrink-0 opacity-0 group-hover:opacity-100 transition-opacity text-muted-foreground">
                    <Blazicon Svg="Lucide.Pencil" class="h-3.5 w-3.5" />
                </span>
            }
        </div>
    }
</div>

@if (!InsideFormField)
{
    @if (EffectiveInvalid && ErrorText is not null)
    {
        <p class="text-xs text-destructive mt-1.5">@ErrorText</p>
    }
    else if (HelperText is not null)
    {
        <p class="text-xs text-muted-foreground mt-1.5">@HelperText</p>
    }
}

@code {
    [CascadingParameter] private FormField.FormFieldContext? FormField { get; set; }

    [Parameter] public string? Value { get; set; }
    [Parameter] public EventCallback<string?> ValueChanged { get; set; }
    [Parameter] public RenderFragment? ChildContent { get; set; }
    [Parameter] public string? Placeholder { get; set; }
    [Parameter] public InplaceEditMode EditMode { get; set; } = InplaceEditMode.Text;
    [Parameter] public List<string>? SelectOptions { get; set; }
    [Parameter] public bool SaveOnBlur { get; set; } = true;
    [Parameter] public bool SaveOnEnter { get; set; } = true;
    [Parameter] public bool ShowButtons { get; set; }
    [Parameter] public bool Disabled { get; set; }
    [Parameter] public EventCallback<string> OnSave { get; set; }
    [Parameter] public EventCallback OnCancel { get; set; }
    [Parameter] public bool Required { get; set; }
    [Parameter] public bool Invalid { get; set; }
    [Parameter] public string? ErrorText { get; set; }
    [Parameter] public string? HelperText { get; set; }
    [Parameter] public string? Label { get; set; }
    [Parameter] public string? Name { get; set; }
    [Parameter] public string? Class { get; set; }
    [Parameter(CaptureUnmatchedValues = true)] public Dictionary<string, object>? AdditionalAttributes { get; set; }

    private bool EffectiveInvalid => Invalid || FormField?.HasError == true;
    private bool InsideFormField => FormField is not null;

    private bool _editing;
    private string? _editValue;

    private string CssClass => $"group w-full {Class}".Trim();
    private string EditInputClass => $"w-full rounded border {(EffectiveInvalid ? "border-destructive focus:ring-destructive/20" : "border-border focus:ring-ring")} bg-background px-2 py-1 text-sm focus:outline-none focus:ring-1";

    private string DisplayClass => string.Join(" ", new[] { "flex items-center w-full rounded px-2 py-1 cursor-pointer hover:bg-muted/30 transition-colors min-h-8", Disabled ? "cursor-default hover:bg-transparent opacity-50 pointer-events-none" : null }.Where(s => !string.IsNullOrWhiteSpace(s)));

    public enum InplaceEditMode { Text, Textarea, Select }

    private void StartEditing()
    {
        if (Disabled) return;
        _editValue = Value;
        _editing = true;
    }

    private void OnInput(ChangeEventArgs e)
    {
        _editValue = e.Value?.ToString();
    }

    private void OnSelectChange(ChangeEventArgs e)
    {
        _editValue = e.Value?.ToString();
    }

    private async Task OnKeyDown(KeyboardEventArgs e)
    {
        if (e.Key == "Escape")
        {
            await Cancel();
        }
        else if (e.Key == "Enter" && SaveOnEnter && EditMode == InplaceEditMode.Text)
        {
            await Save();
        }
    }

    private async Task OnBlur()
    {
        if (SaveOnBlur && _editing && !ShowButtons)
        {
            await Save();
        }
    }

    private async Task Save()
    {
        _editing = false;
        var saved = _editValue ?? "";
        await ValueChanged.InvokeAsync(saved);
        await OnSave.InvokeAsync(saved);
    }

    private async Task Cancel()
    {
        _editing = false;
        _editValue = Value;
        await OnCancel.InvokeAsync();
    }
}
