@page "/Account/Login"

@using System.ComponentModel.DataAnnotations
@using Microsoft.AspNetCore.Authentication
@using Microsoft.AspNetCore.Identity
@using RobotNet.IdentityServer.Data

@inject SignInManager<ApplicationUser> SignInManager
@inject ILogger<Login> Logger
@inject NavigationManager NavigationManager
@inject IdentityRedirectManager RedirectManager

<PageTitle>Log in</PageTitle>

<div class="w-100 h-100 d-flex flex-column justify-content-center align-items-center">
    <h1>Log in</h1>
    @if (!string.IsNullOrEmpty(errorMessage))
    {
        var statusMessageClass = errorMessage.StartsWith("Error") ? "danger" : "success";
        <div class="alert alert-@statusMessageClass" role="alert">
            @errorMessage
        </div>
    }
    <EditForm Model="Input" method="post" OnValidSubmit="LoginUser" FormName="login" style="width: 300px;">
        <DataAnnotationsValidator />
        <hr />
        <ValidationSummary class="text-danger" role="alert" />
        <div class="form-floating mb-3">
            <InputText @bind-Value="Input.Username" class="form-control" autocomplete="username" aria-required="true" />
            <label for="username" class="form-label">Username</label>
            <ValidationMessage For="() => Input.Username" class="text-danger" />
        </div>
        <div class="form-floating mb-3">
            <InputText type="password" @bind-Value="Input.Password" class="form-control" autocomplete="current-password" aria-required="true" />
            <label for="password" class="form-label">Password</label>
            <ValidationMessage For="() => Input.Password" class="text-danger" />
        </div>
        <div class="checkbox mb-3">
            <label class="form-label">
                <InputCheckbox @bind-Value="Input.RememberMe" class="darker-border-checkbox form-check-input" />
                Remember me
            </label>
        </div>
        <div>
            <button type="submit" class="w-100 btn btn-lg btn-primary">Log in</button>
        </div>
    </EditForm>
</div>


@code {
    private string? errorMessage;

    [CascadingParameter]
    private HttpContext HttpContext { get; set; } = default!;

    [SupplyParameterFromForm]
    private InputModel Input { get; set; } = new();

    [SupplyParameterFromQuery]
    private string? ReturnUrl { get; set; }

    protected override async Task OnInitializedAsync()
    {
        if (HttpMethods.IsGet(HttpContext.Request.Method))
        {
            // Clear the existing external cookie to ensure a clean login process
            await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme);
        }

        errorMessage = HttpContext.Request.Cookies[IdentityRedirectManager.StatusCookieName];

        if (errorMessage is not null)
        {
            HttpContext.Response.Cookies.Delete(IdentityRedirectManager.StatusCookieName);
        }
    }

    public async Task LoginUser()
    {
        // This doesn't count login failures towards account lockout
        // To enable password failures to trigger account lockout, set lockoutOnFailure: true
        var result = await SignInManager.PasswordSignInAsync(Input.Username, Input.Password, Input.RememberMe, lockoutOnFailure: false);
        if (result.Succeeded)
        {
            Logger.LogInformation("User logged in.");
            RedirectManager.RedirectTo(ReturnUrl);
        }
        else if (result.RequiresTwoFactor)
        {
            RedirectManager.RedirectTo(
                "Account/LoginWith2fa",
                new() { ["returnUrl"] = ReturnUrl, ["rememberMe"] = Input.RememberMe });
        }
        else if (result.IsLockedOut)
        {
            Logger.LogWarning("User account locked out.");
            RedirectManager.RedirectTo("Account/Lockout");
        }
        else
        {
            errorMessage = "Error: Invalid login attempt.";
        }
    }

    private sealed class InputModel
    {
        [Required]
        public string Username { get; set; } = "";

        [Required]
        [DataType(DataType.Password)]
        public string Password { get; set; } = "";

        [Display(Name = "Remember me?")]
        public bool RememberMe { get; set; }
    }
}
