@page "/account/security"

@using Moonlight.App.Models.Forms
@using Moonlight.App.Services
@using Moonlight.App.Services.Users
@using OtpNet
@using QRCoder
@using Moonlight.App.Models.Enums
@using Moonlight.App.Models.Forms.Auth

@inject IdentityService IdentityService
@inject UserService UserService
@inject ToastService ToastService

<AccountNavigation Index="1"/>

<div class="row mt-5">
    <div class="col-md-6 col-12">
        <div class="card">
            <SmartForm Model="PasswordForm" OnValidSubmit="OnPasswordSubmit">
                <div class="card-body">
                    <div class="row">
                        <div class="col-md-6 col-12">
                            <div>
                                <label class="form-label">New password</label>
                                <input @bind="PasswordForm.Password" type="password" class="form-control">
                            </div>
                        </div>
                        <div class="col-md-6 col-12">
                            <div>
                                <label class="form-label">New password repeated</label>
                                <input @bind="PasswordForm.RepeatedPassword" type="password" class="form-control">
                            </div>
                        </div>
                    </div>
                </div>
                <div class="card-footer">
                    <div class="text-end">
                        <button type="submit" class="btn btn-primary">Update password</button>
                    </div>
                </div>
            </SmartForm>
        </div>
    </div>
    <div class="col-md-6 col-12">
        @if (IdentityService.Flags[UserFlag.TotpEnabled])
        {
            <div class="card card-body fs-6">
                <span class="card-title text-success">Your account is secured with 2fa</span>
                <div class="text-center">
                    <ConfirmButton OnClick="OnDisable2FA" Text="Disable 2fa" CssClasses="btn btn-danger" WorkingText="Disabling"/>
                </div>
            </div>
        }
        else if (!IdentityService.Flags[UserFlag.TotpEnabled] && IdentityService.CurrentUser.TotpKey != null)
        {
            <div class="card">
                <div class="card-body fs-6">
                    <p>
                        Scan the qr code and enter the code generated by the app you have scanned it in
                    </p>
                    @{
                        QRCodeGenerator qrGenerator = new QRCodeGenerator();

                        var qrCodeData = qrGenerator.CreateQrCode
                            (
                                $"otpauth://totp/{Uri.EscapeDataString(IdentityService.CurrentUser.Email)}?secret={IdentityService.CurrentUser.TotpKey}&issuer={Uri.EscapeDataString("Moonlight")}",
                                QRCodeGenerator.ECCLevel.Q
                            );

                        PngByteQRCode qrCode = new PngByteQRCode(qrCodeData);
                        byte[] qrCodeAsPngByteArr = qrCode.GetGraphic(5);
                        var base64 = Convert.ToBase64String(qrCodeAsPngByteArr);
                    }
                    <div class="text-center">
                        <img src="data:image/png;base64,@(base64)" alt="QR Code" class="img-fluid">
                    </div>
                    <div class="mt-3 text-center">
                        <span class="h3">@(IdentityService.CurrentUser.TotpKey)</span>
                    </div>
                </div>
                <div class="card-footer">
                    <SmartForm Model="CodeForm" OnValidSubmit="On2FASubmit">
                        <div class="input-group">
                            <input @bind="CodeForm.Code" type="number" class="form-control"/>
                            <button type="submit" class="btn btn-primary">Enable 2fa</button>
                        </div>
                    </SmartForm>
                </div>
            </div>
        }
        else
        {
            <div class="card card-body fs-6">
                <span class="card-title">Secure your account using 2fa</span>
                <p>
                    Make sure you have installed one of the following apps on your smartphone and continue
                </p>

                <a href="https://support.google.com/accounts/answer/1066447?hl=en" target="_blank">Google Authenticator</a>
                <br/>
                <a href="https://www.microsoft.com/en-us/account/authenticator" target="_blank">Microsoft Authenticator</a>
                <br/>
                <a href="https://authy.com/download/" target="_blank">Authy</a>
                <br/>
                <a href="https://support.1password.com/one-time-passwords/" target="_blank">1Password</a>
                <br/>
                <div class="text-center">
                    <WButton OnClick="OnSeed2FA" Text="Enable 2fa" CssClasses="btn btn-primary"/>
                </div>
            </div>
        }
    </div>
</div>

@code
{
    private UpdateAccountPasswordForm PasswordForm = new();
    private TwoFactorCodeForm CodeForm = new();

    private async Task OnPasswordSubmit()
    {
        if (PasswordForm.Password != PasswordForm.RepeatedPassword)
            throw new DisplayException("The passwords do not match");

        await UserService.Auth.ChangePassword(IdentityService.CurrentUser, PasswordForm.Password);
        await ToastService.Success("Successfully updated your password");
        await IdentityService.Authenticate();
    }

    private async Task OnDisable2FA()
    {
        await UserService.Auth.SetTotp(IdentityService.CurrentUser, false);
        await IdentityService.Authenticate();
        await InvokeAsync(StateHasChanged);
    }

    private async Task OnSeed2FA()
    {
        await UserService.Auth.SeedTotp(IdentityService.CurrentUser);
        await IdentityService.Authenticate();
        await InvokeAsync(StateHasChanged);
    }

    private async Task On2FASubmit()
    {
        var totp = new Totp(Base32Encoding.ToBytes(IdentityService.CurrentUser.TotpKey));
        var code = totp.ComputeTotp();

        if (code != CodeForm.Code)
            throw new DisplayException("The 2fa code you entered is invalid");

        CodeForm = new();

        await UserService.Auth.SetTotp(IdentityService.CurrentUser, true);
        await IdentityService.Authenticate();
        await InvokeAsync(StateHasChanged);
    }
}