@page "/login"
@rendermode InteractiveServer
@using Microsoft.AspNetCore.Components
@using Microsoft.JSInterop
@inject IJSRuntime JS
@inject NavigationManager Navigation

<PageTitle>Log In - Forge</PageTitle>

<div class="auth-card">
    <h1>Log In</h1>
    <p class="auth-copy">Use the configured Forge credentials to create repositories and push over Git HTTP.</p>

    @if (Error)
    {
        <p class="auth-error">Invalid username or password.</p>
    }

    <form method="post" action="/auth/login" class="auth-form">
        <AntiforgeryToken />
        <input type="hidden" name="returnUrl" value="@SanitizedReturnUrl" />

        <div class="form-group">
            <label for="username">Username</label>
            <input id="username" name="username" autocomplete="username" required />
        </div>

        <div class="form-group">
            <label for="password">Password</label>
            <input id="password" name="password" type="password" autocomplete="current-password" required />
        </div>

        <button type="submit" class="btn-primary">Log In</button>
    </form>

    <div class="auth-divider">
        <span>or</span>
    </div>

    <button type="button" class="btn-passkey" @onclick="SignInWithPasskey" disabled="@passkeyDisabled">
        <svg viewBox="0 0 24 24" width="20" height="20" fill="currentColor">
            <path d="M12 2C9.243 2 7 4.243 7 7v2H6c-1.103 0-2 .897-2 2v9c0 1.103.897 2 2 2h12c1.103 0 2-.897 2-2v-9c0-1.103-.897-2-2-2h-1V7c0-2.757-2.243-5-5-5zm0 2c1.654 0 3 1.346 3 3v2H9V7c0-1.654 1.346-3 3-3zm0 10c1.103 0 2 .897 2 2s-.897 2-2 2-2-.897-2-2 .897-2 2-2z"/>
        </svg>
        @if (passkeyDisabled)
        {
            <span>Passkeys not available</span>
        }
        else
        {
            <span>Sign in with Passkey</span>
        }
    </button>
    
    <p class="passkey-hint">Register a passkey in Settings first</p>
    
    @if (passkeyError != null)
    {
        <p class="auth-error">@passkeyError</p>
    }
</div>

@code {
    [SupplyParameterFromQuery] public string? ReturnUrl { get; set; }
    [SupplyParameterFromQuery(Name = "error")] public string? ErrorValue { get; set; }

    private string SanitizedReturnUrl =>
        !string.IsNullOrWhiteSpace(ReturnUrl) && Uri.IsWellFormedUriString(ReturnUrl, UriKind.Relative) && ReturnUrl.StartsWith('/')
            ? ReturnUrl
            : "/admin";

    private bool Error =>
        string.Equals(ErrorValue, "true", StringComparison.OrdinalIgnoreCase)
        || string.Equals(ErrorValue, "1", StringComparison.Ordinal);

    private bool passkeyDisabled = true; // Disabled until we confirm available
    private string? passkeyError;

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            // Check if WebAuthn is available (requires HTTPS or localhost)
            var available = await JS.InvokeAsync<bool>("forge.webauthn.isAvailable");
            passkeyDisabled = !available;
            StateHasChanged();
        }
    }

    private async Task SignInWithPasskey()
    {
        passkeyError = null;
        
        try
        {
            Console.WriteLine($"[Login] Starting passkey sign-in, WebAuthn available: {!passkeyDisabled}");
            var resultJson = await JS.InvokeAsync<string>("forge.webauthn.signIn", SanitizedReturnUrl);
            Console.WriteLine($"[Login] Sign-in result: {resultJson}");
            
            var result = System.Text.Json.JsonSerializer.Deserialize<Dictionary<string, string>>(resultJson);
            
            if (result != null && result.TryGetValue("redirect", out var redirect))
            {
                Navigation.NavigateTo(redirect, forceLoad: true);
            }
            else if (result != null && result.TryGetValue("error", out var error))
            {
                passkeyError = error;
            }
            else
            {
                passkeyError = "Passkey authentication failed. Check browser console for details.";
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"[Login] Exception: {ex}");
            passkeyError = $"Passkey error: {ex.Message}";
        }
    }
}
An unhandled error has occurred. Reload 🗙