@page "/Account/Manage/ChangePassword"

@using System.ComponentModel.DataAnnotations
@using Microsoft.AspNetCore.Identity
@using Wave.Data

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

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

<StatusMessage Message="@Message" />
<BoardComponent>
    <BoardCardComponent Heading="@Localizer["Title"]">
        <EditForm Model="Input" FormName="change-password" OnValidSubmit="OnValidSubmitAsync" method="post">
            <DataAnnotationsValidator />
            
            <InputLabelComponent LabelText="@Localizer["OldPassword_Label"]" For="() => Input.OldPassword">
                <InputText type="password" @bind-Value="Input.OldPassword" class="input input-bordered w-full" autocomplete="current-password" 
                           required aria-required="true" placeholder="@Localizer["OldPassword_Placeholder"]" />
            </InputLabelComponent>
            <InputLabelComponent LabelText="@Localizer["NewPassword_Label"]" For="() => Input.NewPassword">
                <InputText type="password" @bind-Value="Input.NewPassword" class="input input-bordered w-full" autocomplete="new-password"
                           required aria-required="true" placeholder="@Localizer["NewPassword_Placeholder"]" />
            </InputLabelComponent>
            <InputLabelComponent LabelText="@Localizer["ConfirmPassword_Label"]" For="() => Input.ConfirmPassword">
                <InputText type="password" @bind-Value="Input.ConfirmPassword" class="input input-bordered w-full" autocomplete="new-password"
                           required aria-required="true" placeholder="@Localizer["ConfirmPassword_Placeholder"]" />
            </InputLabelComponent>

            <button type="submit" class="btn btn-primary w-full">
                @Localizer["ChangePassword_Submit"]
            </button>
        </EditForm>
    </BoardCardComponent>
</BoardComponent>

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

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

    private string? Message { get; set; }
    private ApplicationUser User { get; set; } = default!;
    private bool HasPassword { get; set; }

    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(Localizer["ChangePassword_Success"], 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; } = "";
    }
}
