//------------------------------------------------------------------------------------
//npm install --save dotenv
require('dotenv').config()

//------------------------------------------------------------------------------------
/*
BEFORE RUNNING THIS EXAMPLE OR CALLING THE paymentLinkMerchantSetUpWalkthrough FUNCTION: 

* Set CONNECTFI_CLIENTID, CONNECTFI_PASSWORD, and CONNECTFI_BASE_URL in a .env file
(Speak to a support representative to be issued client credentials and URL after 
receiving access to the sandbox.)

* Pass in a unique UNIQUE_REFERENCE_ID when calling the 
paymentLinkMerchantSetUpWalkthrough function.
*/

//------------------------------------------------------------------------------------

const CONNECTFI_CLIENTID = process.env.CONNECTFI_CLIENTID;
const CONNECTFI_PASSWORD = process.env.CONNECTFI_PASSWORD;
const CONNECTFI_BASE_URL = process.env.CONNECTFI_BASE_URL;



//------------------------------------------------------------------------------------
//Get Authorization Token
/*
Your first request in any workflow should be to /auth/get-token in order to receive 
an authorization token. A valid token from this endpoint should be included in the 
headers of all /payment-link requests as 'x-connectfi-token'.

*/
async function getAuthToken(login, password) {
    const body = JSON.stringify({
        "user": {
            "login": `${login}`,
            "password": `${password}`
        }
    });
    console.log(JSON.stringify(body));
    const config = {
        method: 'POST',
        url: `${CONNECTFI_BASE_URL}/auth/get-token`,
        headers: {
            'Content-Type': "application/json"
        },
        body
    };

    let response;
    try {
        response = await fetch(config.url, config);
        const data = await response.json();
        if (!response.ok) {
            throw new Error(JSON.stringify(data));
        }
        return data.data;
    } catch (err) {
        console.log(err);
    }
}



//------------------------------------------------------------------------------------
//Create Merchant
/*
After authenticating, you may make a request to create a merchant. The term merchant refers 
to the payee, or payment requester/recipient when using the Payment Link API. Example
default merchant data is used here.
*/
async function createMerchant(authToken, reference) {
    const body = JSON.stringify({
        "reference": reference, //reference must be unique
        "name": `Merchant${reference.length > 4 ? reference.substring(reference.length - 4) : reference}`,
        "isArchived": false,
        "email": "abc.test@email.test",
        "phone": "5556667777",
        "address": "123 Main Street",
        "city": "Oklahoma City",
        "stateCode": "OK",
        "postalCode": "12345",
        "availablePaymentType": [
            "ach",
            "card"
        ],
        "usePlaid": true
    });
    const config = {
        method: 'POST',
        url: `${CONNECTFI_BASE_URL}/payment-link/merchant/create`,
        headers: {
            'Content-Type': "application/json",
            'x-connectfi-token': authToken //previously obtained authorization token is required
        },
        body
    };

    let response;
    try {
        response = await fetch(config.url, config);
        const data = await response.json();
        if (!response.ok) {
            throw new Error(JSON.stringify(data));
        }
        return data.data;
    } catch (err) {
        console.log(err);
    }
}



//------------------------------------------------------------------------------------
//Update Merchant
/*
Once a merchant is created, you may update the merchant properties if necessary.
*/
async function updateMerchant(authToken, cFiMerchantId, reference) {

    const body = JSON.stringify({
        cFiMerchantId,
        name: `Merchant${reference.length > 4 ? reference.substring(reference.length - 4) : reference}`,
        email: "def.test@email.test",
        phone: "5557776666",
        address: "1346 Pleasant Ave",
        city: "New York",
        stateCode: "NY",
        postalCode: "12345",
        isArchived: false,
        availablePaymentType: [
            "ach",
            "card"
        ],
        usePlaid: true
    });
    const config = {
        method: 'POST',
        url: `${CONNECTFI_BASE_URL}/payment-link/merchant/update`,
        headers: {
            'Content-Type': "application/json",
            'x-connectfi-token': authToken //previously obtained authorization token is required
        },
        body
    };

    let response;
    try {
        response = await fetch(config.url, config);
        const data = await response.json();
        if (!response.ok) {
            throw new Error(JSON.stringify(data));
        }
        return data.data;
    } catch (err) {
        console.log(err);
    }
}



//------------------------------------------------------------------------------------
//Merchant Details
/*
You may also retrieve the merchant details.
*/
async function retrieveMerchantDetails(authToken, cFiMerchantId) {

    const body = JSON.stringify({
        cFiMerchantId
    });
    const config = {
        method: 'POST',
        url: `${CONNECTFI_BASE_URL}/payment-link/merchant/details`,
        headers: {
            'Content-Type': "application/json",
            'x-connectfi-token': authToken //previously obtained authorization token is required
        },
        body
    };

    let response;
    try {
        response = await fetch(config.url, config);
        const data = await response.json();
        if (!response.ok) {
            throw new Error(JSON.stringify(data));
        }
        return data.data;
    } catch (err) {
        console.log(err);
    }
}



//------------------------------------------------------------------------------------
//Get Merchant Token
/*
In order to display the Payment Link iframe or to make any /public/merchant requests, you
will need to retrieve a merchant access token (JWT). The merchant token will be included
as a header called 'x-connectfi-jwtoken'.
*/
async function getMerchantToken(authToken, cFiMerchantId) {

    const body = JSON.stringify({
        cFiMerchantId
    });
    const config = {
        method: 'POST',
        url: `${CONNECTFI_BASE_URL}/payment-link/merchant/get-token`,
        headers: {
            'Content-Type': "application/json",
            'x-connectfi-token': authToken //previously obtained authorization token is required
        },
        body
    };

    let response;
    try {
        response = await fetch(config.url, config);
        const data = await response.json();
        if (!response.ok) {
            throw new Error(JSON.stringify(data));
        }
        return data.data;
    } catch (err) {
        console.log(err);
    }
}



//------------------------------------------------------------------------------------
//Run the walkthrough
async function paymentLinkMerchantSetUpWalkthrough(login = CONNECTFI_CLIENTID, password = CONNECTFI_PASSWORD, reference) {

    //Get Authorization Token
    console.log(`Start /auth/get-token example.\n`);
    const authObject = await getAuthToken(login, password);
    let authToken = undefined;

    if (authObject) {
        console.log(`Successfully obtained authorization: ${JSON.stringify(authObject)}\n`);
        authToken = authObject.token;
        console.log(`Authorization token: ${authToken}\n`);
    } else {
        console.log(`Error getting authorization token\n`);
    }
    console.log(`End /auth/get-token example.\n`);

    //Create Merchant
    console.log(`Start /payment-link/merchant/create example.\n`);
    let merchant;
    let cFiMerchantId = undefined;
    if (authToken) {
        merchant = await createMerchant(authToken, reference);
    } else {
        console.log(`Authorization token is required. Merchant not created.\n`);
    }
    if (merchant) {
        console.log(`Successfully created new merchant: ${JSON.stringify(merchant)}\n`);
        cFiMerchantId = merchant.cFiMerchantId;
        console.log(`cFiMerchantId: ${cFiMerchantId}\n`);
    }
    console.log(`End /payment-link/merchant/create example.\n`);

    //Update Merchant

    console.log(`Start /payment-link/merchant/update example.\n`);
    if (authToken && cFiMerchantId) {
        merchant = await updateMerchant(authToken, cFiMerchantId, reference);
    } else {
        console.log(`Authorization token and cFiMerchantId are required. Merchant not updated.\n`);
    }
    if (merchant) {
        console.log(`Successfully updated merchant: ${JSON.stringify(merchant)}\n`);
    }
    console.log(`End /payment-link/merchant/update example.\n`);


    //Retrieve Merchant Details

    console.log(`Start /payment-link/merchant/details example.\n`);
    if (authToken && cFiMerchantId) {
        merchant = await retrieveMerchantDetails(authToken, cFiMerchantId);
    } else {
        console.log(`Authorization token and cFiMerchantId are required. Merchant not retrieved.\n`);
    }
    if (merchant) {
        console.log(`Successfully retrieved merchant: ${JSON.stringify(merchant)}\n`);
    }
    console.log(`End /payment-link/merchant/details example.\n`);


    //Get Merchant Token
    /* Can be uncommented in order to get the merchant token as part of the walkthrough in the CLI instead
    of getting the token separately if desired.

    console.log(`Start /payment-link/merchant/get-token example.\n`);
    let response = undefined;
    let merchantToken = undefined;
    if (authToken && cFiMerchantId) {
        response = await getMerchantToken(authToken, cFiMerchantId);
    } else {
        console.log(`Authorization token and cFiMerchantId are required. Merchant token not obtained.\n`);
    }
    if (response) {
        console.log(`Successfully obtained merchant access token (JWT): ${JSON.stringify(response)}\n`);
        merchantToken = response.token;
        console.log(`Merchant token ('x-connectfi-jwtoken' header): ${merchantToken}\n`);

    }
    console.log(`End /payment-link/merchant/get-token example.\n`);
    */

    console.log(`The cFiMerchantId is: ${cFiMerchantId}\n`);

    return {
        cFiMerchantId
    }

}

// If calling from the CLI, you can use the following command:
// node ./src/payment-link-merchant-setup-walkthrough.js PUT_UNIQUE_REFERENCE_HERE
if (process.argv[2]) {
    paymentLinkMerchantSetUpWalkthrough(undefined, undefined, process.argv[2]);
}
module.exports = { paymentLinkMerchantSetUpWalkthrough };