@page "/Account/Manage/ChangePassword"

@using System.ComponentModel.DataAnnotations
@using Microsoft.AspNetCore.Identity
@using OpenArchival.Blazor.Data

@inject UserManager<ApplicationUser> UserManager
@inject SignInManager<ApplicationUser> SignInManager
@inject IdentityUserAccessor UserAccessor
@inject IdentityRedirectManager RedirectManager
@inject ILogger<ChangePassword> Logger

<PageTitle>Change password</PageTitle>

<MudText Typo="Typo.h6" GutterBottom="true">Change password</MudText>

<StatusMessage Message="@message" />

<EditForm Model="Input" FormName="change-password" OnValidSubmit="OnValidSubmitAsync" method="post">
    <DataAnnotationsValidator />

    <MudGrid>
        <MudItem md="12">
            <MudStaticTextField For="@(() => Input.OldPassword)" @bind-Value="Input.OldPassword" InputType="InputType.Password"
                                Label="Old Password" Placeholder="old password" HelperText="Please enter your old password."
                                UserAttributes="@(new() { { "autocomplete", "current-password" }, { "aria-required", "true" } } )" />
        </MudItem>
        <MudItem md="12">
            <MudStaticTextField For="@(() => Input.NewPassword)" @bind-Value="Input.NewPassword" InputType="InputType.Password"
                                Label="New Password" Placeholder="new password" HelperText="Please enter your new password."
                                UserAttributes="@(new() { { "autocomplete", "new-password" }, { "aria-required", "true" } } )" />
        </MudItem>
        <MudItem md="12">
            <MudStaticTextField For="@(() => Input.ConfirmPassword)" @bind-Value="Input.ConfirmPassword" InputType="InputType.Password"
                                Label="Confirm Password" Placeholder="confirm password" HelperText="Please confirm your new password."
                                UserAttributes="@(new() { { "autocomplete", "new-password" }, { "aria-required", "true" } } )" />
        </MudItem>
        <MudItem md="12">
            <MudStaticButton Variant="Variant.Filled" Color="Color.Primary" FullWidth="true" FormAction="FormAction.Submit">Update password</MudStaticButton>
        </MudItem>
    </MudGrid>
</EditForm>

@code {
    private string? message;
    private ApplicationUser user = default!;
    private bool hasPassword;

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

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

    protected override async Task OnInitializedAsync()
    {
        user = await UserAccessor.GetRequiredUserAsync(HttpContext);
        hasPassword = await UserManager.HasPasswordAsync(user);
        if (!hasPassword)
        {
            RedirectManager.RedirectTo("Account/Manage/SetPassword");
        }
    }

    private async Task OnValidSubmitAsync()
    {
        var changePasswordResult = await UserManager.ChangePasswordAsync(user, Input.OldPassword, Input.NewPassword);
        if (!changePasswordResult.Succeeded)
        {
            message = $"Error: {string.Join(",", changePasswordResult.Errors.Select(error => error.Description))}";
            return;
        }

        await SignInManager.RefreshSignInAsync(user);
        Logger.LogInformation("User changed their password successfully.");

        RedirectManager.RedirectToCurrentPageWithStatus("Your password has been changed", HttpContext);
    }

    private sealed class InputModel
    {
        [Required]
        [DataType(DataType.Password)]
        [Display(Name = "Current password")]
        public string OldPassword { 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 = "New password")]
        public string NewPassword { get; set; } = "";

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