@inherits AliasVault.Client.Auth.Pages.Base.LoginBase
@using System.Timers
@using Microsoft.Extensions.Localization
@using AliasVault.Client.Main.Components.Shared
@using AliasVault.Client.Main.Components.Loading
@using AliasVault.Client.Main.Constants
@using AliasVault.Client.Auth.Components

<div class="w-full mx-auto">
   @if (_isLoading)
    {
        <div class="absolute inset-0 flex justify-center items-center z-10">
            <div class="animate-spin rounded-full h-16 w-16 border-t-2 border-b-2 border-primary-500"></div>
        </div>
    }
    <div class="@(_isLoading ? "invisible opacity-0" : "opacity-100") transition-opacity duration-300 w-full">
        <div class="bg-white dark:bg-gray-800 rounded-lg shadow-lg lg:shadow-none p-6">
            <div class="flex items-start mb-4">
                <div class="flex-shrink-0">
                    <img class="h-10 w-10 rounded-full" src="/img/avatar.webp" alt="AliasVault Assistant">
                </div>
                <div class="ml-3 bg-blue-100 dark:bg-blue-900 rounded-lg p-3">
                    <p class="text-sm text-gray-900 dark:text-white">
                        @Localizer["WelcomeMessage"]
                    </p>
                </div>
            </div>
        </div>

        <div class="p-4 mb-6 bg-gray-100 dark:bg-gray-900 rounded-lg text-gray-900 dark:text-gray-100">
            <p class="text-sm font-semibold">
                @Localizer["ImportantNote"]
            </p>
            <ul class="text-sm mt-3 list-disc list-inside">
                <li>@Localizer["SecurityPoint1"]</li>
                <li>@Localizer["SecurityPoint2"]</li>
                <li>@Localizer["SecurityPoint3"]</li>
            </ul>
        </div>

        <div class="space-y-4">
            <div>
                <div class="">
                    <label for="password" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">@Localizer["MasterPasswordLabel"]</label>
                    <PasswordInputField Id="password" @bind-Value="Password" Placeholder="@Localizer["MasterPasswordPlaceholder"]" @onfocus="@OnPasswordInputFocus" />
                </div>

                <PasswordStrengthIndicator Password="@Password" />

                <div class="mt-4">
                    <label for="confirmPassword" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">@Localizer["ConfirmMasterPasswordLabel"]</label>
                    <PasswordInputField Id="confirmPassword" @bind-Value="ConfirmPassword" Placeholder="@Localizer["ConfirmMasterPasswordPlaceholder"]" @onfocus="@OnPasswordInputFocus" />
                </div>
                @if (!string.IsNullOrEmpty(_errorMessage))
                {
                    <div class="mt-2 text-sm text-red-600 dark:text-red-400">@_errorMessage</div>
                }
            </div>
        </div>
    </div>
</div>

@code {
    private IStringLocalizer Localizer => LocalizerFactory.Create("Components.Auth.Setup.PasswordStep", "AliasVault.Client");
    private IStringLocalizer ValidationLocalizer => LocalizerFactory.Create("ValidationMessages", "AliasVault.Client");

    /// <summary>
    /// The event callback for when the password changes.
    /// </summary>
    [Parameter]
    public EventCallback<string> OnPasswordChange { get; set; }

    private string Password
    {
        get => _password;
        set
        {
            if (_password != value)
            {
                _password = value;
                ValidatePasswordWithDebounce();
            }
        }
    }

    private string ConfirmPassword
    {
        get => _confirmPassword;
        set
        {
            if (_confirmPassword != value)
            {
                _confirmPassword = value;
                ValidatePasswordImmediate();
            }
        }
    }

    private string _password = string.Empty;
    private string _confirmPassword = string.Empty;
    private string _errorMessage = string.Empty;
    private Timer? _debounceTimer;

    private bool _isLoading = true;
    private Timer? _loadingTimer;

    /// <inheritdoc />
    protected override void Dispose(bool disposing)
    {
        _loadingTimer?.Dispose();
        _debounceTimer?.Dispose();
        base.Dispose(disposing);
    }

    /// <inheritdoc />
    protected override void OnInitialized()
    {
        _loadingTimer = new Timer(300);
        _loadingTimer.Elapsed += (sender, e) => FinishLoading();
        _loadingTimer.AutoReset = false;
        _loadingTimer.Start();

        _debounceTimer = new Timer(800);
        _debounceTimer.Elapsed += async (sender, e) => await ValidatePasswordDebounced();
        _debounceTimer.AutoReset = false;
    }

    /// <inheritdoc />
    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        await base.OnAfterRenderAsync(firstRender);
        if (firstRender)
        {
            await Task.Delay(100); // Give time for the DOM to update
            await JsInteropService.FocusElementById("password");
        }
    }

    /// <summary>
    /// Finishes the loading animation.
    /// </summary>
    private void FinishLoading()
    {
        _isLoading = false;
        InvokeAsync(StateHasChanged);
    }

    /// <summary>
    /// Validates the password with debounce (for main password field).
    /// </summary>
    private void ValidatePasswordWithDebounce()
    {
        _errorMessage = string.Empty;
        StateHasChanged();

        _debounceTimer?.Stop();
        _debounceTimer?.Start();
    }

    /// <summary>
    /// Validates the password immediately (for confirm password field).
    /// </summary>
    private async void ValidatePasswordImmediate()
    {
        await ValidatePasswordDebounced();
    }

    /// <summary>
    /// Validates the password after input has stopped.
    /// </summary>
    private async Task ValidatePasswordDebounced()
    {
        await InvokeAsync(async () =>
        {
            if (Password.Length < PasswordStrengthConstants.MinimumGoodPasswordLength)
            {
                _errorMessage = ValidationLocalizer["PasswordMinLengthGeneric", PasswordStrengthConstants.MinimumGoodPasswordLength];
                await OnPasswordChange.InvokeAsync(string.Empty);
                StateHasChanged();
                return;
            }

            if (string.IsNullOrWhiteSpace(ConfirmPassword))
            {
                _errorMessage = string.Empty;
                await OnPasswordChange.InvokeAsync(string.Empty);
                StateHasChanged();
                return;
            }

            if (Password != ConfirmPassword)
            {
                _errorMessage = ValidationLocalizer["PasswordsDoNotMatchGeneric"];
                await OnPasswordChange.InvokeAsync(string.Empty);
                StateHasChanged();
                return;
            }

            // If password is valid.
            _errorMessage = string.Empty;
            await OnPasswordChange.InvokeAsync(Password);
            StateHasChanged();
        });
    }

    /// <summary>
    /// Handles the password input focus.
    /// </summary>
    private void OnPasswordInputFocus(FocusEventArgs args)
    {
        // Reset validation state when the input is focused.
        _errorMessage = string.Empty;
        StateHasChanged();
    }
}
