@inherits AliasVault.Client.Auth.Pages.Base.LoginBase
@implements IDisposable
@using System.Timers

<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 mb-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">
                        Great! Now, let's set up your username for AliasVault.
                    </p>
                    <p class="text-sm text-gray-900 dark:text-white mt-3">
                        Please enter a username you'd like to use. This can be your email address or any unique name you prefer.
                    </p>
                    <p class="text-sm text-gray-900 dark:text-white mt-3 font-semibold">
                        Remember: This is what you'll use to log in later, so make sure it's something you'll remember!
                    </p>
                </div>
            </div>
        </div>

        <div class="space-y-4">
            <div>
                <EditFormRow Id="username" Label="Username" @bind-Value="Username" Placeholder="Enter your desired username or email" OnFocus="@OnUsernameInputFocus" />
                @if (_isValidating)
                {
                    <div class="mt-2 text-sm text-gray-600 dark:text-gray-400">Validating username...</div>
                }
                else if (_isValid)
                {
                    <div class="mt-2 text-sm text-green-600 dark:text-green-400">Username is available!</div>
                }
                else if (!string.IsNullOrEmpty(_errorMessage))
                {
                    <div class="mt-2 text-sm text-red-600 dark:text-red-400">@_errorMessage</div>
                }
            </div>
        </div>
    </div>
</div>

@code {
    /// <summary>
    /// The username that is previously entered by the user. When a user navigates with back/continue
    /// and entered a username already, the existing username might be provided by the parent component.
    /// </summary>
    [Parameter]
    public string DefaultUsername { get; set; } = string.Empty;

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

    private string _username = string.Empty;
    private bool _isValid = false;
    private bool _isValidating = false;
    private string _errorMessage = string.Empty;
    private Timer? _debounceTimer;

    /// <summary>
    /// The username that is entered by the user. This is the value that will be validated and sent to the parent component.
    /// </summary>
    private string Username
    {
        get => _username;
        set
        {
            if (_username != value)
            {
                _username = value;
                ValidateUsername();
            }
        }
    }

    private bool _isLoading = true;
    private Timer? _loadingTimer;

    /// <inheritdoc />
    public void Dispose()
    {
        _loadingTimer?.Dispose();
        _debounceTimer?.Dispose();
    }

    /// <inheritdoc />
    protected override async Task OnInitializedAsync()
    {
        // Set the default username if provided.
        _username = DefaultUsername;

        if (!string.IsNullOrWhiteSpace(DefaultUsername))
        {
            await ValidateUsernameDebounced();
        }

        _loadingTimer = new Timer(300);
        _loadingTimer.Elapsed += (sender, e) => FinishLoading();
        _loadingTimer.AutoReset = false;
        _loadingTimer.Start();

        _debounceTimer = new Timer(300);
        _debounceTimer.Elapsed += async (sender, e) => await ValidateUsernameDebounced();
        _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("username");
        }
    }

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

    /// <summary>
    /// Validates the username immediately.
    /// </summary>
    private void ValidateUsername()
    {
        _isValidating = true;
        _isValid = false;
        _errorMessage = string.Empty;
        StateHasChanged();

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

    /// <summary>
    /// Validates the username after input has stopped.
    /// </summary>
    private async Task ValidateUsernameDebounced()
    {
        await InvokeAsync(async () =>
        {
            if (string.IsNullOrWhiteSpace(Username))
            {
                _isValidating = false;
                _isValid = false;
                _errorMessage = "Username is required.";
                await OnUsernameChange.InvokeAsync(string.Empty);
                StateHasChanged();
                return;
            }

            try
            {
                var response = await Http.PostAsJsonAsync("v1/Auth/validate-username", new { Username });

                if (response.IsSuccessStatusCode)
                {
                    _isValid = true;
                    _errorMessage = string.Empty;
                    await OnUsernameChange.InvokeAsync(Username);
                }
                else
                {
                    var error = await response.Content.ReadAsStringAsync();
                    _errorMessage = error;
                    _isValid = false;
                    await OnUsernameChange.InvokeAsync(string.Empty);
                }
            }
            catch
            {
                _errorMessage = "An error occurred during communication with the AliasVault server.";
                _isValid = false;
                await OnUsernameChange.InvokeAsync(string.Empty);
            }
            finally
            {
                _isValidating = false;
                StateHasChanged();
            }
        });
    }

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