@page "/Account/accept-invite"

@using System.ComponentModel.DataAnnotations
@using Microsoft.AspNetCore.Identity
@using WishNinja.Data
@using WishNinja.Services

@inject InviteService InviteService
@inject IdentityRedirectManager RedirectManager

<PageTitle>Accept invitation</PageTitle>

<h1>Set up your account</h1>

@if (invite is null)
{
    <div class="alert alert-danger" role="alert">
        This invite link is invalid or has expired. Please ask an administrator for a new invitation.
    </div>
    <p><a href="Account/Login">Back to sign in</a></p>
}
else
{
    <p>You're joining as <strong>@invite.Email</strong>. Choose a display name and password.</p>
    <div class="row">
        <div class="col-md-5">
            <StatusMessage Message="@Message" />
            <EditForm Model="Input" FormName="accept-invite" OnValidSubmit="OnValidSubmitAsync" method="post">
                <DataAnnotationsValidator />
                <ValidationSummary class="text-danger" role="alert" />

                <input type="hidden" name="Input.Token" value="@Input.Token" />
                <div class="form-floating mb-3">
                    <InputText @bind-Value="Input.DisplayName" id="Input.DisplayName" class="form-control" autocomplete="name" placeholder="Your name" />
                    <label for="Input.DisplayName">Display name</label>
                    <ValidationMessage For="() => Input.DisplayName" class="text-danger" />
                </div>
                <div class="form-floating mb-3">
                    <InputText type="password" @bind-Value="Input.Password" id="Input.Password" class="form-control" autocomplete="new-password" placeholder="Password" />
                    <label for="Input.Password">Password</label>
                    <ValidationMessage For="() => Input.Password" class="text-danger" />
                </div>
                <div class="form-floating mb-3">
                    <InputText type="password" @bind-Value="Input.ConfirmPassword" id="Input.ConfirmPassword" class="form-control" autocomplete="new-password" placeholder="Confirm password" />
                    <label for="Input.ConfirmPassword">Confirm password</label>
                    <ValidationMessage For="() => Input.ConfirmPassword" class="text-danger" />
                </div>
                <button type="submit" class="w-100 btn btn-lg btn-primary">Create account</button>
            </EditForm>
        </div>
    </div>
}

@code {
    private Data.Entities.Invite? invite;
    private IEnumerable<IdentityError>? identityErrors;

    [SupplyParameterFromForm]
    private InputModel Input { get; set; } = default!;

    [SupplyParameterFromQuery(Name = "token")]
    private string? Token { get; set; }

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

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

    protected override async Task OnInitializedAsync()
    {
        Input ??= new();
        // On first GET the token is in the query; on post it round-trips via the hidden field.
        var rawToken = !string.IsNullOrEmpty(Input.Token) ? Input.Token : Token;
        Input.Token = rawToken ?? "";
        invite = await InviteService.GetValidInviteAsync(Input.Token);
    }

    private async Task OnValidSubmitAsync()
    {
        var result = await InviteService.AcceptInviteAsync(Input.Token, Input.DisplayName, Input.Password);
        if (result.Succeeded)
        {
            RedirectManager.RedirectToWithStatus("Account/Login", "Account created — please sign in.", HttpContext);
            return;
        }
        identityErrors = result.Errors;
    }

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

        [Required, StringLength(100, MinimumLength = 2)]
        [Display(Name = "Display name")]
        public string DisplayName { get; set; } = "";

        [Required]
        [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)]
        [DataType(DataType.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; } = "";
    }
}
