import {fetch_timeout} from "./util";
import {Logger, logSetup} from "./logger";
import {API_ROOT} from "./config";

const logger = new Logger("totp.ts");
logSetup();

export interface TOTPSetupDetails {
    totpToken: string,
    secret: string,
    url: string
}

export async function startTotpSetup(api_key: string): Promise<TOTPSetupDetails | string> {
    logger.info("Starting TOTP setup");
    try {
        const resp = await fetch_timeout(`${API_ROOT}/v1/totp-authenticators`, {
            'method': 'POST',
            'headers': {
                'Content-Type': 'application/json',
                'Authorization': `Bearer ${api_key}`
            },
            'body': "{}"
        });
        if (!resp.ok) {
            const rawerror = JSON.parse(await resp.text()).errors[0].message;
            logger.error(`API returned error setting up TOTP: ${rawerror}`);
            return rawerror;
        }
        logger.info('Initiated TOTP setup successfully');
        return (await resp.json()).data as TOTPSetupDetails;
    } catch (e) {
        logger.error(`Error while trying to setup TOTP: ${e}`);
        return `${e}`
    }
}

export interface TOTPToken {
    token: string
}

export async function finishTOTPSetup(api_key: string, token: string, code: string): Promise<TOTPToken | string> {
    logger.info("Finishing up TOTP setup");
    try {
        const resp = await fetch_timeout(`${API_ROOT}/v1/verify-totp-authenticator`, {
            'method': 'POST',
            'headers': {
                'Content-Type': 'application/json',
                'Authorization': `Bearer ${api_key}`
            },
            'body': `{"totpToken":"${token}","code":"${code}"}`
        });
        if (!resp.ok) {
            const rawerror = JSON.parse(await resp.text()).errors[0].message;
            logger.error(`API returned error finishing up TOTP: ${rawerror}`);
            return rawerror;
        }
        logger.info('Finished TOTP setup! Auth token issued');
        return {
            token: (await resp.json()).data.authToken
        };
    } catch (e) {
        logger.error(`Error while trying to finish TOTP: ${e}`);
        return `${e}`
    }
}

export async function validateTOTP(api_key: string, code: string): Promise<TOTPToken | string> {
    logger.info("Validating 2fa code");
    try {
        const resp = await fetch_timeout(`${API_ROOT}/v1/auth/totp`, {
            'method': 'POST',
            'headers': {
                'Content-Type': 'application/json',
                'Authorization': `Bearer ${api_key}`
            },
            'body': `{"code":"${code}"}`
        });
        if (!resp.ok) {
            const rawerror = JSON.parse(await resp.text()).errors[0].message;
            logger.error(`API returned error verifying TOTP: ${rawerror}`);
            return rawerror;
        }
        logger.info('auth token issued');
        return {
            token: (await resp.json()).data.authToken
        };
    } catch (e) {
        logger.error(`Error while trying to validate TOTP: ${e}`);
        return `${e}`
    }
}