<script lang="ts">
    import {onMount} from "svelte";
    import {enforce_session} from "$lib/auth";
    import {Logger, logSetup} from "$lib/logger";
    import {get_user_info} from "$lib/auth";
    import type {UserInfo} from "$lib/auth";
    import {t} from "$lib/i18n";
    import {startTotpSetup} from "$lib/totp";
    import {browser} from "$app/environment";
    import QR from "../../../components/QR.svelte";
    import {finishTOTPSetup} from "$lib/totp";
    import {setCookie} from "$lib/cookie";

    let logger = new Logger("auth/mfasetup/+page.svelte");
    logSetup();

    let api_token = "";
    let isLoadingMFA = true;

    let hasError = false;
    let error = "";

    let totp_setup_token = "";
    let totp_otpurl = "";
    let totp_secret = "";
    let mfa_token = "";

    let isloading = false;

    onMount(async () => {
        let st_res = await enforce_session();
        if (!st_res[0]) {
            // session token is invalid
            // Session token is invalid. redirect to mfa
            logger.info("Invalid session token, redirecting to mfa");
            window.location = "/auth/mfa";
            return;
        }
        api_token = st_res[1];
        let user: UserInfo | string = await get_user_info(api_token);
        if (typeof user === "string") {
            logger.error(`Unable to get user info: ${user}`);
            hasError = true;
            error = user;
            return;
        }
        if (user.data.actor.hasTOTPAuthenticator) {
            logger.info("User already has mfa set up, redirecting");
            window.location = "/auth/mfa";
            return;
        }

        let resp = await startTotpSetup(api_token);
        if (typeof resp === "string") {
            logger.error(`Unable to create TOTP token: ${resp}`);
            hasError = true;
            error = t(`mfasetup.apierror.${resp}`);
            return;
        }

        totp_setup_token = resp.totpToken;
        totp_secret = resp.secret;
        totp_otpurl = resp.url;

        isLoadingMFA = false;

    });

    function validateInput(e: KeyboardEvent) {
        if (e.charCode === 13) { return; }
        if (e.charCode < 47 || e.charCode > 57) {
            e.preventDefault();
        }
        if (e.target.value.length >= 6) {
            e.preventDefault();
        }
    }

    async function tryMFACode() {
        isloading = true;
        logger.info(`Submitting 2FA verify with code ${mfa_token}`);
        let resp = await finishTOTPSetup(api_token, totp_setup_token, mfa_token);
        if (typeof resp === "string") {
            logger.error(`Unable to validate TOTP token: ${resp}`);
            hasError = true;
            isloading = false;
            error = t(`mfasetup.apierror.${resp}`);
            return;
        }
        // set cookie
        setCookie("authToken", resp.token);
        window.location = "/admin";
        window.location.reload();
    }
</script>

<sveltekit:head>
    <script src="https://cdn.jsdelivr.net/gh/davidshimjs/qrcodejs/qrcode.min.js"></script>
</sveltekit:head>

<div class="flex in-h-full items-center justify-center py-12 px-4 sm:px-6 lg:px-8">
    <div class="w-full max-w-md">
        <h1 class="font-semibold text-2xl">{t('mfasetup.title')}</h1>
        <h2 class="text-sm">{t('mfasetup.subtitle')}</h2>

        {#if isLoadingMFA}
            <div class="mt-5">
                <svg class="animate-spin w-5 h-5 inline-block m-auto" xmlns="http://www.w3.org/2000/svg"
                     fill="none" viewBox="0 0 24 24">
                    <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor"
                            stroke-width="4"></circle>
                    <path class="opacity-75" fill="currentColor"
                          d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
                </svg>
                <h3 class="text-xs inline-block">{t('mfasetup.loadingmfa')}</h3>
            </div>
        {:else}
            <h4 class="text-sm mt-5 font-semibold ">{t('mfasetup.qrtitle')}</h4>
            <div class="mt-2 dark:bg-slate-600 bg-slate-200 rounded aspect-square p-4 w-min">
                <QR codeValue="{totp_otpurl}"/>
            </div>
            <h4 class="text-sm mt-5">{t('mfasetup.secrettitle')}</h4>
            <span class="font-mono text-md mt-4 block">
                {totp_secret.match(/.{1,4}/g).join(" ")}
            </span>

            <form class="mt-5" action="#" method="POST" on:submit|preventDefault={tryMFACode}>
                <div class="-space-y-px rounded-md shadow-sm">
                    <input on:keypress={validateInput} bind:value={mfa_token} type="number" id="mfa_token" placeholder="{t('mfasetup.verifytitle')}"
                           class="dark:bg-slate-500 bg-gray-200 w-full rounded px-3 py-2 focus:outline-none focus:ring-purple-500 appearance-none">
                    {#if hasError}
                        <span class="text-red-600 text-sm">{error}</span>
                    {/if}
                </div>

                <button class="-space-y-px bg-purple-400 dark:bg-purple-600 mt-4 w-full py-2 rounded-md shadow-sm place-content-center">
                    {#if !isloading}
                        {t('mfasetup.actionButtonText')}
                    {:else}
                        <svg class="animate-spin w-5 h-5 inline-block m-auto" xmlns="http://www.w3.org/2000/svg"
                             fill="none" viewBox="0 0 24 24">
                            <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor"
                                    stroke-width="4"></circle>
                            <path class="opacity-75" fill="currentColor"
                                  d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
                        </svg>
                    {/if}
                </button>
            </form>
        {/if}
    </div>
</div>