@page "/Account/Register"

@using System.ComponentModel.DataAnnotations
@using System.Text
@using System.Text.Encodings.Web
@using Microsoft.AspNetCore.Authentication
@using Microsoft.AspNetCore.Identity
@using Microsoft.AspNetCore.WebUtilities
@using RobotNet.IdentityServer.Data

@inject UserManager<ApplicationUser> UserManager
@inject IUserStore<ApplicationUser> UserStore
@inject SignInManager<ApplicationUser> SignInManager
@inject IEmailSender<ApplicationUser> EmailSender
@inject ILogger<Register> Logger
@inject NavigationManager NavigationManager
@inject IdentityRedirectManager RedirectManager


<PageTitle>Register</PageTitle>

<div class="w-100 h-100 d-flex flex-column justify-content-center align-items-center">
    <h1>Create a new account.</h1>
    @if (!string.IsNullOrEmpty(errorMessage))
    {
        var statusMessageClass = errorMessage.StartsWith("Error") ? "danger" : "success";
        <div class="alert alert-@statusMessageClass" role="alert">
            @errorMessage
        </div>
    }
    <EditForm style="width:500px" Model="Input" asp-route-returnUrl="@ReturnUrl" method="post" OnValidSubmit="RegisterUser" FormName="register">
        <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" placeholder="name" />
            <label for="user">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="new-password" aria-required="true" placeholder="password" />
            <label for="password">Password</label>
            <ValidationMessage For="() => Input.Password" class="text-danger" />
        </div>
        <div class="form-floating mb-3">
            <InputText type="password" @bind-Value="Input.ConfirmPassword" class="form-control" autocomplete="new-password" aria-required="true" placeholder="password" />
            <label for="confirm-password">Confirm Password</label>
            <ValidationMessage For="() => Input.ConfirmPassword" class="text-danger" />
        </div>
        <button type="submit" class="w-100 btn btn-lg btn-primary">Register</button>
    </EditForm>
</div>


@code {
    private string errorMessage = string.Empty;

    private IEnumerable<IdentityError>? identityErrors;

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

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

    private string? Message => identityErrors is null ? null : $"Error: {string.Join(", ", identityErrors.Select(error => error.Description))}";

    public async Task RegisterUser(EditContext editContext)
    {
        var user = CreateUser();

        await UserStore.SetUserNameAsync(user, Input.UserName, CancellationToken.None);
        user.NormalizedUserName = Input.UserName.ToUpperInvariant();
        user.EmailConfirmed = true;
        var result = await UserManager.CreateAsync(user, Input.Password);

        if (!result.Succeeded)
        {
            identityErrors = result.Errors;
            return;
        }

        Logger.LogInformation("User created a new account with password.");

        await SignInManager.SignInAsync(user, isPersistent: false);
        RedirectManager.RedirectTo(ReturnUrl);
    }

    private ApplicationUser CreateUser()
    {
        try
        {
            return Activator.CreateInstance<ApplicationUser>();
        }
        catch
        {
            throw new InvalidOperationException($"Can't create an instance of '{nameof(ApplicationUser)}'. " +
                $"Ensure that '{nameof(ApplicationUser)}' is not an abstract class and has a parameterless constructor.");
        }
    }


    private sealed class InputModel
    {
        [Required]
        [Display(Name = "UserName")]
        public string UserName { get; set; } = "";

        [Required]
        [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)]
        [DataType(DataType.Password)]
        [Display(Name = "Password")]
        public string Password { get; set; } = "";

        [DataType(DataType.Password)]
        [Display(Name = "Confirm password")]
        [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
        public string ConfirmPassword { get; set; } = "";
    }
}
