const qs = require('qs')
const axios = require('axios')
const findProperty = require('./findProperty')
const CRM = require('../models/CRM')

const { set, get, del } = require('./redisClient')
const get75PercentTimeInSeconds = require('./get75PercentTimeInSeconds')

const exchangeForTokens = async (crmOauth, exchangeProof) => {

    const { request, body, response } = findProperty(crmOauth.crm.crmRest, 'tokenEndpoint')

    let { requestContentType, requestEncoding, requestType, responseType, url } = request

    let config = {
        method: requestType,
        url,
        data: qs.stringify(exchangeProof)
    }

    if (requestContentType != 'none') {
        config = {
            ...config, headers: {
                'Content-Type': requestContentType
            }
        }
    }

    console.log('======> CONFIG: ', config)

    // const { data } = await axios(config)

     

    //test 
    let data
        try {
            let { data: _data } = await axios(config)
            data = _data
        } catch (error) { 
            if (error.response) {
                console.error('==================> oauth2 Erro na resposta da API:', {
                    status: error.response.status,
                    data: error.response.data,
                })
            } 
            else if (error.request) {
                console.error('==================> oauth2 Nenhuma resposta recebida da API:', error.request)
            } 
            else {
                console.error('==================> oauth2 Erro ao configurar a request:', error.message)
            }
     
            throw error
        }

    //

    const { refresh_token, access_token, token_type, expires_in, issued_at } = data

    console.log('===========> refresh_token: ', refresh_token)
    console.log('===========> access_token: ', access_token)

    // salesforce case
    if (issued_at)
        await set(crmOauth.crm.authentication.crmClientId, access_token, get75PercentTimeInSeconds(issued_at))
    else
        await set(crmOauth.crm.authentication.crmClientId, access_token, Math.round(expires_in * 0.75))

    crmOauth = await CRM.findOne({ 'crm.authentication.crmClientId': crmOauth.crm.authentication.crmClientId })

    if (refresh_token) {
        crmOauth.crm.authentication.crmOAuthRefreshToken = refresh_token
    }
    crmOauth.crm.authentication.crmOAuthToken = access_token
    await crmOauth.save()

    return access_token

}

const refreshAccessToken = async (clientId) => {

    let crmOauth = await CRM.findOne({ 'crm.authentication.crmClientId': clientId })
    crmOauth = crmOauth.toObject()

    const refreshTokenProof = {
        grant_type: 'refresh_token',
        client_id: crmOauth.crm.authentication.crmClientId,
        client_secret: crmOauth.crm.authentication.crmClientSecret,
        redirect_uri: process.env.URL_OAUTH_CALLBACK,
        refresh_token: crmOauth.crm.authentication.crmOAuthRefreshToken
    }
    return await exchangeForTokens(crmOauth, refreshTokenProof)
}

const getAccessToken = async (clientId) => {

    if (!await get(clientId)) {
        console.log('Refreshing expired access token')
        await refreshAccessToken(clientId)
    }
    return await get(clientId)
}


module.exports = {
    exchangeForTokens,
    refreshAccessToken,
    getAccessToken
}