@page "/register"
@using Iceshrimp.Frontend.Core.Miscellaneous
@using Iceshrimp.Frontend.Core.Schemas
@using Iceshrimp.Frontend.Core.Services
@using Iceshrimp.Shared.Schemas.Web
@using Microsoft.Extensions.Localization
@using Iceshrimp.Frontend.Components
@layout UnauthLayout
@inject IStringLocalizer<Register> Loc;
@inject MetadataService            Metadata;
@inject ApiService                 Api;
@inject SessionService             SessionService;
@inject NavigationManager          Navigation;

<HeadTitle Text="@Loc["Register"]"/>

@if (State is State.Loaded)
{
    <div class="body">
        <img class="logo" src="/_content/Iceshrimp.Assets.Branding/splash.png"/>
        <span>
            <h3>@Loc["Register on {0}", Name ?? "this Iceshrimp.NET Instance."]</h3></span>
        @if (RegistrationAvailability is not Registrations.Closed)
        {
            @if (Rules.Count != 0 && AcceptedRules == false)
            {
                <div class="rules">
                    <span>@Loc["To register you must accept the following rules"]</span>
                    <ol>
                        @foreach (var rule in Rules)
                        {
                            <li>
                                @rule.Text
                                @if (rule.Description != null)
                                {
                                    <br>
                                    <i>@rule.Description</i>
                                }
                            </li>
                        }
                    </ol>
                    <button class="button" @onclick="() => { AcceptedRules = true; }">@Loc["Accept"]</button>
                </div>
            }
            else
            {
                <div class="register-form">
                    <input placeholder="@Loc["Username"]" autocomplete="username" name="username" required="required"
                           @bind="@Username"/>
                    <input type="password" autocomplete="new-password" name="new-password" required="required"
                           placeholder="@Loc["Password"]"
                           @bind="@Password"/>
                    @if (RegistrationAvailability is Registrations.Invite)
                    {
                        <input required="required" placeholder="@Loc["Invite"]" @bind="@Invite"/>
                    }
                    <StateButton @ref="@LoginButton" ExtraClasses="button" OnClick="Submit">
                        <Initial>@Loc["Register"]</Initial>
                        <Success>@Loc["Success!"]</Success>
                        <Loading>@Loc["Loading"] <LoadingSpinner /></Loading>
                        <Failed>@Loc["Try again"]</Failed>
                    </StateButton>
                </div>
            }

            @if (Error)
            {
                <div>@Loc[RegistrationError ?? string.Empty]</div>
            }
        }
        @if (RegistrationAvailability is Registrations.Closed)
        {
            <div>@Loc["Registrations for this instance are closed."]</div>
        }
        <a class="login-link" href="/login">@Loc["Login to an existing account"]</a>
    </div>
}

@code {
    private string?       Username                 { get; set; }
    private string?       Password                 { get; set; }
    private string?       Invite                   { get; set; }
    private bool          Error                    { get; set; }
    private Registrations RegistrationAvailability { get; set; }
    private State         State                    { get; set; } = State.Loading;
    private string?       RegistrationError        { get; set; }
    private string?       Name                     { get; set; }
    private StateButton   LoginButton              { get; set; } = null!;
    private bool          AcceptedRules            { get; set; }

    private List<RuleResponse> Rules { get; set; } = [];

    private async Task Submit()
    {
        LoginButton.State = StateButton.StateEnum.Loading;
        StateHasChanged();
        if (Username is null || Password is null)
        {
            Error             = true;
            LoginButton.State = StateButton.StateEnum.Failed;
            RegistrationError = "Please fill out all fields";
            return;
        }

        var registration = new RegistrationRequest { Username = Username, Password = Password, Invite = Invite, };
        try
        {
            var res = await Api.Auth.RegisterAsync(registration);
            if (res.Status is AuthStatusEnum.Authenticated)
            {
                SessionService.AddUser(new StoredUser
                { // Token nor user will ever be null on an authenticated response
                    Id              = res.User!.Id,
                    Username        = res.User.Username,
                    DisplayName     = res.User.DisplayName,
                    AvatarUrl       = res.User.AvatarUrl,
                    BannerUrl       = res.User.BannerUrl,
                    InstanceName    = res.User.InstanceName,
                    InstanceIconUrl = res.User.InstanceIconUrl,
                    Token           = res.Token!,
                    Host            = res.User.Host,
                    IsAdmin         = res.IsAdmin ?? false,
                    IsModerator     = res.IsModerator ?? false,
                    Emojis          = res.User.Emojis,
                    MovedTo         = res.User.MovedTo
                });
                SessionService.SetSession(res.User.Id);
                LoginButton.State = StateButton.StateEnum.Success;
                Navigation.NavigateTo("/");
            }

        }
        catch (ApiException e)
        {
            RegistrationError = e.Response.Message;
            Error             = true;
            LoginButton.State = StateButton.StateEnum.Failed;
            StateHasChanged();
        }
    }

    protected override async Task OnInitializedAsync()
    {
        var metadata = await Metadata.Instance.Value;
        RegistrationAvailability = metadata.Registration;
        State                    = State.Loaded;
        Name                     = metadata.Name;
        Rules                    = await Api.Instance.GetRulesAsync();
    }
}