@page "/settings/security/enable-2fa"
@using AliasVault.Client.Main.Pages.Settings.Security.Components
@using Microsoft.Extensions.Localization
@inherits MainBase
@inject HttpClient Http

<LayoutPageTitle>@Localizer["PageTitle"]</LayoutPageTitle>

<div class="grid grid-cols-1 px-4 pt-6 xl:grid-cols-3 xl:gap-4 dark:bg-gray-900">
    <div class="mb-4 col-span-full xl:mb-2">
        <Breadcrumb BreadcrumbItems="BreadcrumbItems"/>
        <H1>@Localizer["PageTitle"]</H1>
        <p class="mt-2 text-sm text-gray-600 dark:text-gray-400">@Localizer["PageDescription"]</p>
    </div>
</div>

@if (IsLoading)
{
    <LoadingIndicator />
}
else if (RecoveryCodes is not null)
{
    <ShowRecoveryCodes RecoveryCodes="RecoveryCodes.ToArray()"/>
}
else
{
    <div class="max-w-2xl mx-auto px-4 lg:mt-8">
        <div class="p-4 mb-4 bg-white border border-gray-200 rounded-lg shadow-sm dark:border-gray-700 sm:p-6 dark:bg-gray-800">
            <div class="space-y-6">
                <div id="authenticator-uri" data-url="@QrCodeUrl" class="flex justify-center">
                    <!-- QR code will be rendered here -->
                </div>

                <p class="text-sm text-gray-600 dark:text-gray-400 text-center">
                    @Localizer["QrCodeInstructions"]
                </p>
                <div class="text-lg font-mono text-center bg-gray-100 dark:bg-gray-700 p-3 rounded border dark:text-gray-200" id="authenticator-secret">@Secret</div>

                <EditForm Model="@VerifyModel" OnValidSubmit="@VerifySetup" class="space-y-4" av-enable="true" av-suppress-save="true">
                    <div>
                        <InputTextOnInput id="verificationCode" @bind-Value="VerifyModel.Code"
                                   class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 dark:bg-gray-700 dark:text-gray-200 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 dark:focus:ring-blue-400"
                                   placeholder="@Localizer["VerificationCodePlaceholder"]"
                                   autocomplete="one-time-code"/>
                    </div>
                    <button type="submit"
                            class="w-full bg-primary-500 text-white py-2 px-4 rounded-md hover:bg-primary-600 focus:outline-none focus:ring-2 focus:ring-primary-500 focus:ring-offset-2 transition duration-150 ease-in-out">
                        @Localizer["VerifyAndEnableButton"]
                    </button>
                </EditForm>
            </div>
        </div>
    </div>
}

@code {
    private string QrCodeUrl { get; set; } = string.Empty;
    private string Secret { get; set; } = string.Empty;
    private bool IsLoading { get; set; } = true;
    private List<string>? RecoveryCodes { get; set; }
    private readonly VerificationModel VerifyModel = new();

    private IStringLocalizer Localizer => LocalizerFactory.Create("Components.Main.Pages.Settings.Security.Enable2Fa", "AliasVault.Client");

    /// <inheritdoc />
    protected override async Task OnInitializedAsync()
    {
        await base.OnInitializedAsync();

        BreadcrumbItems.Add(new BreadcrumbItem { DisplayName = Localizer["BreadcrumbSecuritySettings"], Url = "/settings/security" });
        BreadcrumbItems.Add(new BreadcrumbItem { DisplayName = Localizer["BreadcrumbEnable2Fa"] });
    }

    /// <inheritdoc />
    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        await base.OnAfterRenderAsync(firstRender);

        // Check on server if 2FA is enabled
        if (firstRender)
        {
            // Get the QR code and secret for the authenticator app.
            var response = await Http.PostAsync("v1/TwoFactorAuth/enable", null);
            if (response.IsSuccessStatusCode)
            {
                var result = await response.Content.ReadFromJsonAsync<TwoFactorSetupResult>();

                if (result != null)
                {
                    QrCodeUrl = result.QrCodeUrl;

                    // Make secret more readable by adding spaces every 4 characters
                    Secret = string.Join(" ", Enumerable.Range(0, result.Secret.Length / 4)
                        .Select(i => result.Secret.Substring(i * 4, 4))).ToLower();

                    IsLoading = false;
                    StateHasChanged();
                    await JsInteropService.GenerateQrCode("authenticator-uri");
                }
            }

            IsLoading = false;
            StateHasChanged();
        }
    }

    private async Task VerifySetup()
    {
        var response = await Http.PostAsJsonAsync("v1/TwoFactorAuth/verify", VerifyModel.Code);
        if (response.IsSuccessStatusCode)
        {
            var result = await response.Content.ReadFromJsonAsync<TwoFactorVerifyResult>();

            if (result != null)
            {
                GlobalNotificationService.AddSuccessMessage(Localizer["TwoFactorEnabledSuccess"], true);

                // Show recovery codes.
                RecoveryCodes = result.RecoveryCodes;
                IsLoading = false;
                StateHasChanged();
                return;
            }
        }

        GlobalNotificationService.AddErrorMessage(Localizer["FailedToEnable2Fa"], true);
        StateHasChanged();
    }

    private sealed class TwoFactorSetupResult
    {
        public required string Secret { get; init; } = string.Empty;
        public required string QrCodeUrl { get; init; } = string.Empty;
    }

    private sealed class TwoFactorVerifyResult
    {
        public required List<string> RecoveryCodes { get; init; } = [];
    }

    private sealed class VerificationModel
    {
        public string Code { get; set; } = string.Empty;
    }
}
