@namespace Lumeo
@inject Lumeo.Services.Localization.ILumeoLocalizer L

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

<div class="@WrapperClass">
    <div class="@($"flex h-9 w-full rounded-md border {(EffectiveInvalid ? "border-destructive" : "border-input")} bg-transparent text-sm overflow-hidden transition-colors {(EffectiveInvalid ? "focus-within:ring-[1.5px] focus-within:ring-destructive/20" : "focus-within:ring-[1.5px] focus-within:ring-ring")}")">
        <input type="@(_showPassword ? "text" : "password")"
               name="@Name"
               aria-required="@Required.ToString().ToLowerInvariant()"
               aria-invalid="@EffectiveInvalid.ToString().ToLowerInvariant()"
               class="flex-1 bg-transparent px-3 py-1 placeholder:text-muted-foreground focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50"
               value="@Value"
               placeholder="@(Placeholder ?? L["Password.Placeholder"])"
               disabled="@Disabled"
               @oninput="HandleInput"
               @attributes="AdditionalAttributes" />
        @if (ShowToggle)
        {
            <button type="button"
                    class="flex items-center px-3 text-muted-foreground hover:text-foreground transition-colors"
                    aria-label="@L["Password.Toggle"]"
                    @onclick="ToggleVisibility"
                    tabindex="-1">
                @if (_showPassword)
                {
                    <Blazicon Svg="Lucide.EyeOff" class="h-4 w-4" />
                }
                else
                {
                    <Blazicon Svg="Lucide.Eye" class="h-4 w-4" />
                }
            </button>
        }
    </div>
    @if (ShowStrength && !string.IsNullOrEmpty(Value))
    {
        <div class="mt-1.5 flex gap-1">
            @for (int i = 0; i < 4; i++)
            {
                var idx = i;
                <div class="@GetStrengthBarClass(idx) h-1 flex-1 rounded-full transition-colors"></div>
            }
        </div>
        <p class="mt-1 text-xs @StrengthLabelClass">@StrengthLabel</p>
    }
</div>

@if (!InsideFormField)
{
    @if (EffectiveInvalid && !string.IsNullOrEmpty(ErrorText))
    {
        <p class="mt-1 text-xs text-destructive">@ErrorText</p>
    }
    else if (!string.IsNullOrEmpty(HelperText))
    {
        <p class="mt-1 text-xs text-muted-foreground">@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 string? Placeholder { get; set; }
    [Parameter] public bool ShowStrength { get; set; }
    [Parameter] public bool ShowToggle { get; set; } = true;
    [Parameter] public bool Disabled { 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 _showPassword;

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

    private string WrapperClass => $"w-full {Class}".Trim();

    private void ToggleVisibility() => _showPassword = !_showPassword;

    private async Task HandleInput(ChangeEventArgs e)
    {
        Value = e.Value?.ToString();
        await ValueChanged.InvokeAsync(Value);
    }

    private int StrengthScore
    {
        get
        {
            if (string.IsNullOrEmpty(Value)) return 0;
            int score = 0;
            if (Value.Length >= 8) score++;
            if (Value.Any(char.IsUpper)) score++;
            if (Value.Any(char.IsLower)) score++;
            if (Value.Any(char.IsDigit)) score++;
            if (Value.Any(c => !char.IsLetterOrDigit(c))) score++;
            return score;
        }
    }

    private int StrengthLevel => StrengthScore switch
    {
        0 or 1 => 1,
        2 => 2,
        3 => 3,
        _ => 4
    };

    private string StrengthLabel => StrengthLevel switch
    {
        1 => L["Password.Weak"],
        2 => L["Password.Fair"],
        3 => L["Password.Good"],
        4 => L["Password.Strong"],
        _ => ""
    };

    private string StrengthLabelClass => StrengthLevel switch
    {
        1 => "text-destructive",
        2 => "text-warning",
        3 => "text-info",
        4 => "text-success",
        _ => "text-muted-foreground"
    };

    private string GetStrengthBarClass(int index) =>
        index < StrengthLevel
            ? StrengthLevel switch
            {
                1 => "bg-destructive",
                2 => "bg-warning",
                3 => "bg-info",
                4 => "bg-success",
                _ => "bg-muted"
            }
            : "bg-muted";
}
