const config = require('../bin/config');

const moment = require('moment');
const request = require('request-promise-native');
const APIURL = !process.env.RANIENV ? 'https://api-cli.sshchain.com.br' : 'http://localhost:3038';

class Auth {

    static create(...args) {
        return new Auth(...args);
    }

    constructor() {

        this._req = request.defaults({
            method: 'POST',
            baseUrl: APIURL,
            json: true,
            headers: {
                'Cache-Control': 'no-cache'
            }
        });
    }

    profile(){
        const ops = {
            method: 'GET',
            uri: `/user/profile`,
            body: {
                username: config.get('userEmail'),
                idtoken: config.get('tokenData.idToken'),
                accesstoken: config.get('tokenData.accessToken')
            }
        };
        return this.req(ops);
    }

    editProfile(attributes = {}) {
        const ops = {
            method: 'POST',
            uri: `/user/profile`,
            body: {
                username: config.get('userEmail'),
                idtoken: config.get('tokenData.idToken'),
                accesstoken: config.get('tokenData.accessToken'),
                attributes: attributes
            }
        };
        return this.req(ops);
    }

    editProfileConfirmAttrChange(attribute, confirmCode) {
        const ops = {
            method: 'POST',
            uri: `/user/profile/attrconfirm`,
            body: {
                username: config.get('userEmail'),
                idtoken: config.get('tokenData.idToken'),
                accesstoken: config.get('tokenData.accessToken'),
                attribute: attribute,
                code: confirmCode
            }
        };
        return this.req(ops);
    }

    register(email, pass){
        const ops = {
            method: 'POST',
            uri: `/auth/register`,
            body: {
                username: email,
                password: pass
            }
        };
        return this.req(ops, false);
    }

    registerResend(email){
        const ops = {
            method: 'POST',
            uri: `/auth/register/resend`,
            body: {
                username: email
            }
        };
        return this.req(ops, false);
    }

    registerConfirm(email, code){
        const ops = {
            method: 'POST',
            uri: `/auth/register/confirm`,
            body: {
                username: email,
                code: code
            }
        };
        return this.req(ops, false);
    }

    async validateSession(){
        const ops = {
            method: 'GET',
            uri: `/auth/session/validate`,
            body: {}
        };

        try {
            await this.req(ops);
            return true;
        } catch(err) {
            console.warn(err.message || err.stack || err);
            return false;
        }
    }

    sessionTimeIsValid() {
        const accessTokenExpiresAt = config.get('tokenData.accessTokenExpiresAt');
        const idTokenExpiresAt = config.get('tokenData.idTokenExpiresAt');
        return (moment().utc().isBefore(moment.unix(accessTokenExpiresAt)) && moment().utc().isBefore(moment.unix(idTokenExpiresAt)));
    }

    refreshSession(force = false) {

        if(!force && this.sessionTimeIsValid()) {
            return true;
        }

        const ops = {
            method: 'GET',
            uri: `/auth/session/refresh`,
            body: {
                username: config.get('userEmail'),
                idtoken: config.get('tokenData.idToken'),
                accesstoken: config.get('tokenData.accessToken'),
                refreshtoken: config.get('tokenData.refreshToken')
            }
        };

        return this.req(ops, false);
    }
    
    login(user, pass){
        const ops = {
            method: 'POST',
            uri: `/auth/login`,
            body: {
                usr: user,
                psd: pass
            }
        };
        return this.req(ops, false);
    }

    loginMFA(confirmCode){
        const ops = {
            method: 'POST',
            uri: `/auth/loginmfa`,
            body: {
                username: config.get('userEmail'),
                session: config.get('loginSessionMFA'),
                code: confirmCode
            }
        };
        return this.req(ops, false);
    }

    logout(){
        const ops = {
            method: 'POST',
            uri: `/auth/logout`,
            body: {
                username: config.get('userEmail'),
                idtoken: config.get('tokenData.idToken'),
                accesstoken: config.get('tokenData.accessToken')
            }
        };
        return this.req(ops, false);
    }

    statusMFA() {
        const ops = {
            method: 'GET',
            uri: `/user/mfa/status`,
            body: {
                username: config.get('userEmail'),
                idtoken: config.get('tokenData.idToken'),
                accesstoken: config.get('tokenData.accessToken')
            }
        };
        return this.req(ops);
    }

    changeStatusMFA(status = true) {
        const ops = {
            method: 'POST',
            uri: `/user/mfa`,
            body: {
                username: config.get('userEmail'),
                idtoken: config.get('tokenData.idToken'),
                accesstoken: config.get('tokenData.accessToken'),
                state: status
            }
        };
        return this.req(ops);
    }

    editPhoneNumber(numberPhone) {
        const ops = {
            method: 'POST',
            uri: `/user/profile/phone`,
            body: {
                username: config.get('userEmail'),
                idtoken: config.get('tokenData.idToken'),
                accesstoken: config.get('tokenData.accessToken'),
                phone: numberPhone
            }
        };
        return this.req(ops);
    }

    req(ops, useToken = true) {

        if(useToken && config.has('tokenData.accessToken')) {
            if(!ops.headers) ops.headers = {};
            ops.headers['accessToken'] = config.get('tokenData.accessToken');
        }
        // console.debug(ops);
        return this._req(ops);
    }
    
}

module.exports = Auth.create();