#include app/info.jsx
#include app/scope.jsx
#include header/header.js
#include header/user.jsx

const MszOAuth2Verify = () => {
    const queryParams = new URLSearchParams(window.location.search);
    const loading = new MszLoading({ element: '.js-loading', size: 2 });
    const header = new MszOAuth2Header;

    const fAuths = document.querySelector('.js-verify-authorise');
    const eAuthsInfo = document.querySelector('.js-verify-authorise-info');
    const eAuthsScope = document.querySelector('.js-verify-authorise-scope');

    const rApproved = document.querySelector('.js-verify-approved');
    const rDenied = document.querySelector('.js-verify-denied');

    let userCode = '';
    let userHeader;

    const verifyAuthsRequest = async approve => {
        try {
            const { body } = await $xhr.post('/oauth2/verify', { authed: true, csrf: true, type: 'json' }, {
                code: userCode,
                approve: approve === true ? 'yes' : 'no',
            });

            if(!body)
                throw 'response is empty';

            if(typeof body.error === 'string') {
                // TODO: nicer errors
                if(body.error === 'auth')
                    alert('You are not logged in.');
                else if(body.error === 'csrf')
                    alert('Request verification failed, please refresh and try again.');
                else if(body.error === 'code')
                    alert('This code is not associated with any authorisation request.');
                else if(body.error === 'approval')
                    alert('The authorisation request associated with this code is not pending approval.');
                else if(body.error === 'expired')
                    alert('The authorisation request has expired, please restart the process from the application or device.');
                else if(body.error === 'invalid')
                    alert('Invalid approval state specified.');
                else if(body.error === 'scope') {
                    alert(`Requested scope "${body.scope}" is ${body.reason}.`);
                    loading.visible = false;
                    rDenied.classList.remove('hidden');
                    return;
                } else
                    alert(`An unknown error occurred: ${body.error}`);

                loading.visible = false;
                fAuths.classList.remove('hidden');
                return;
            }

            loading.visible = false;
            if(body.approval === 'approved')
                rApproved.classList.remove('hidden');
            else
                rDenied.classList.remove('hidden');
        } catch(ex) {
            alert('Request to verify endpoint failed. Please try again.');
            loading.visible = false;
            fAuths.classList.remove('hidden');
        }
    };

    fAuths.onsubmit = ev => {
        ev.preventDefault();

        loading.visible = true;
        fAuths.classList.add('hidden');

        if(userHeader)
            userHeader.guiseVisible = false;

        verifyAuthsRequest(ev.submitter.value === 'yes');
    };

    const fCode = document.querySelector('.js-verify-code');
    const eUserCode = fCode.elements.namedItem('code');

    fCode.onsubmit = ev => {
        ev.preventDefault();

        loading.visible = true;
        fCode.classList.add('hidden');

        userCode = encodeURIComponent(eUserCode.value);
        $xhr.get(`/oauth2/resolve-verify?code=${userCode}`, { authed: true, csrf: true, type: 'json' })
            .then(result => {
                const body = result.body;

                if(!body) {
                    alert('Request to resolve endpoint failed. Please try again.');
                    loading.visible = false;
                    fCode.classList.remove('hidden');
                    return;
                }

                if(typeof body.error === 'string') {
                    // TODO: nicer errors
                    if(body.error === 'auth') {
                        window.location.assign(`/auth/login.php?oauth2=1&redirect=${encodeURIComponent(`${window.location.pathname}${window.location.search}`)}`);
                        return;
                    } else if(body.error === 'csrf')
                        alert('Request verification failed, please refresh and try again.');
                    else if(body.error === 'code')
                        alert('This code is not associated with any authorisation request.');
                    else if(body.error === 'expired')
                        alert('The authorisation request has expired, please restart the process from the application or device.');
                    else if(body.error === 'approval')
                        alert('The authorisation request associated with this code is not pending approval.');
                    else if(body.error === 'scope') {
                        verifyAuthsRequest(false).finally(() => {
                            alert(`Requested scope "${body.scope}" is ${body.reason}.`);
                        });
                        return;
                    } else
                        alert(`An unknown error occurred: ${body.error}`);

                    loading.visible = false;
                    fCode.classList.remove('hidden');
                    return;
                }

                userCode = body.req.code;

                userHeader = new MszOAuth2UserHeader(body.user);
                header.setElement(userHeader);

                if(body.app.trusted && body.user.guise === undefined) {
                    if(userHeader)
                        userHeader.guiseVisible = false;

                    verifyAuthsRequest(true);
                    return;
                }

                eAuthsInfo.replaceWith(new MszOAuth2AppInfo(body.app).element);
                eAuthsScope.replaceWith(new MszOAuth2AppScopeList(body.scope).element);

                loading.visible = false;
                fAuths.classList.remove('hidden');
            }).catch(() => {
                alert('Request to resolve endpoint failed. Please try again.');
                loading.visible = false;
                fCode.classList.remove('hidden');
            });
    };

    const validateCodeInput = () => {
        // [A-Za-z0-8]{3}\-[A-Za-z0-8]{3}\-[A-Za-z0-8]{3}
        // 0 -> O, 1 -> I, 8 -> B

        const eCode = eUserCode.value;

        return eCode.length > 0;
    };

    eUserCode.oninput = () => {
        validateCodeInput();
        console.warn(eUserCode.value);
    };

    if(queryParams.has('code') && eUserCode.value === '')
        eUserCode.value = queryParams.get('code');

    if(validateCodeInput()) {
        fCode.requestSubmit();
    } else {
        loading.visible = false;
        fCode.classList.remove('hidden');
    }
};