"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.PluggyClient = void 0;
const baseApi_1 = require("./baseApi");
const paymentsClient_1 = require("./paymentsClient");
/**
 * Creates a new client instance for interacting with Pluggy API
 * @constructor
 * @param API_KEY for authenticating to the API
 * @returns {PluggyClient} a client for making requests
 */
class PluggyClient extends baseApi_1.BaseApi {
    constructor(params) {
        super(params);
        this.payments = new paymentsClient_1.PluggyPaymentsClient(params);
    }
    /**
     * Fetch all available connectors
     * @returns {PageResponse<Connector>} paged response of connectors
     */
    fetchConnectors(options = {}) {
        return __awaiter(this, void 0, void 0, function* () {
            return yield this.createGetRequest('connectors', options);
        });
    }
    /**
     * Fetch a single Connector
     * @param id The Connector ID
     * @returns {Connector} a connector object
     */
    fetchConnector(id) {
        return __awaiter(this, void 0, void 0, function* () {
            return yield this.createGetRequest(`connectors/${id}`);
        });
    }
    /**
     * Fetch a single item
     * @param id The Item ID
     * @returns {Item} a item object
     */
    fetchItem(id) {
        return __awaiter(this, void 0, void 0, function* () {
            return yield this.createGetRequest(`items/${id}`);
        });
    }
    /**
     * Check that connector parameters are valid
     * @param id The Connector ID
     * @param parameters A map of name and value for the credentials to be validated
     * @returns {ValidationResult} an object with the info of which parameters are wrong
     */
    validateParameters(id, parameters) {
        return __awaiter(this, void 0, void 0, function* () {
            return yield this.createPostRequest(`connectors/${id}/validate`, null, parameters);
        });
    }
    /**
     * Creates an item
     * @param connectorId The Connector's id
     * @param parameters A map of name and value for the needed credentials
     * @param options Options available to set to the item
     * @returns {Item} a item object
     */
    createItem(connectorId, parameters, options) {
        return __awaiter(this, void 0, void 0, function* () {
            return yield this.createPostRequest(`items`, null, Object.assign({ connectorId,
                parameters }, (options || {})));
        });
    }
    /**
     * Updates an item
     * @param id The Item ID
     * @param parameters A map of name and value for the credentials to be updated.
     *                   Optional; if none submitted, an Item update will be attempted with the latest used credentials.
     * @returns {Item} a item object
     */
    updateItem(id, parameters, options) {
        return __awaiter(this, void 0, void 0, function* () {
            return yield this.createPatchRequest(`items/${id}`, null, Object.assign({ id,
                parameters }, (options || {})));
        });
    }
    /**
     * Send MFA for item execution
     * @param id The Item ID
     * @param parameters A map of name and value for the mfa requested
     * @returns {Item} a item object
     */
    updateItemMFA(id, parameters = undefined) {
        return __awaiter(this, void 0, void 0, function* () {
            return yield this.createPostRequest(`items/${id}/mfa`, null, parameters);
        });
    }
    /**
     * Deletes an item
     */
    deleteItem(id) {
        return __awaiter(this, void 0, void 0, function* () {
            yield this.createDeleteRequest(`items/${id}`);
        });
    }
    /**
     * Fetch accounts from an Item
     * @param itemId The Item id
     * @returns {PageResponse<Account>} paged response of accounts
     */
    fetchAccounts(itemId, type) {
        return __awaiter(this, void 0, void 0, function* () {
            return yield this.createGetRequest('accounts', { itemId, type });
        });
    }
    /**
     * Fetch a single account
     * @returns {Account} an account object
     */
    fetchAccount(id) {
        return __awaiter(this, void 0, void 0, function* () {
            return yield this.createGetRequest(`accounts/${id}`);
        });
    }
    /**
     * Fetch transactions from an account
     * @param accountId The account id
     * @param {TransactionFilters} options Transaction options to filter
     * @returns {PageResponse<Transaction[]>} object which contains the transactions list and related paging data
     */
    fetchTransactions(accountId, options = {}) {
        return __awaiter(this, void 0, void 0, function* () {
            return yield this.createGetRequest('transactions', Object.assign(Object.assign({}, options), { accountId }));
        });
    }
    /**
     * Fetch all transactions from an account
     * @param accountId The account id
     * @param {TransactionFilters} options Optional transaction filters
     * @returns {Transaction[]} an array of transactions
     */
    fetchAllTransactions(accountId, options = {}) {
        return __awaiter(this, void 0, void 0, function* () {
            const MAX_PAGE_SIZE = 500;
            const { totalPages, results: firstPageResults } = yield this.fetchTransactions(accountId, Object.assign(Object.assign({}, options), { pageSize: MAX_PAGE_SIZE }));
            if (totalPages === 1) {
                // just one page return transactions
                return firstPageResults;
            }
            const transactions = [...firstPageResults];
            // first page already fetched
            let page = 1;
            while (page < totalPages) {
                page++;
                const paginatedTransactions = yield this.fetchTransactions(accountId, Object.assign(Object.assign({}, options), { page, pageSize: MAX_PAGE_SIZE }));
                transactions.push(...paginatedTransactions.results);
            }
            return transactions;
        });
    }
    /**
     * Fetch account statements from an account
     * @param accountId The account id
     * @returns {PageResponse<AccountStatement[]>} object which contains the Account statements list and related paging data
     */
    fetchAccountStatements(accountId) {
        return __awaiter(this, void 0, void 0, function* () {
            return yield this.createGetRequest(`accounts/${accountId}/statements`);
        });
    }
    /**
     * Post transaction user category for transactin
     * @param id The Transaction id
     *
     * @returns {Transaction} updated transaction object
     */
    updateTransactionCategory(id, categoryId) {
        return __awaiter(this, void 0, void 0, function* () {
            return yield this.createPatchRequest(`transactions/${id}`, null, {
                categoryId,
            });
        });
    }
    /**
     * Fetch a single transaction
     *
     * @returns {Transaction} an transaction object
     */
    fetchTransaction(id) {
        return __awaiter(this, void 0, void 0, function* () {
            return yield this.createGetRequest(`transactions/${id}`);
        });
    }
    /**
     * Fetch investments from an Item
     *
     * @param itemId The Item id
     * @returns {PageResponse<Investment>} paged response of investments
     */
    fetchInvestments(itemId, type, options = {}) {
        return __awaiter(this, void 0, void 0, function* () {
            return yield this.createGetRequest('investments', Object.assign(Object.assign({}, options), { itemId,
                type }));
        });
    }
    /**
     * Fetch a single investment
     *
     * @returns {Investment} an investment object
     */
    fetchInvestment(id) {
        return __awaiter(this, void 0, void 0, function* () {
            return yield this.createGetRequest(`investments/${id}`);
        });
    }
    /**
     * Fetch transactions from an investment
     *
     * @param investmentId The investment id
     * @param {TransactionFilters} options Transaction options to filter
     * @returns {PageResponse<InvestmentTransaction[]>} object which contains the transactions list and related paging data
     */
    fetchInvestmentTransactions(investmentId, options = {}) {
        return __awaiter(this, void 0, void 0, function* () {
            return yield this.createGetRequest(`investments/${investmentId}/transactions`, Object.assign(Object.assign({}, options), { investmentId }));
        });
    }
    /**
     * Fetch all investment transactions from an investment
     * @param investmentId The investment id
     * @returns {InvestmentTransaction[]} an array of investment transactions
     */
    fetchAllInvestmentTransactions(investmentId) {
        return __awaiter(this, void 0, void 0, function* () {
            const MAX_PAGE_SIZE = 500;
            const { totalPages, results: firstPageResults, } = yield this.fetchInvestmentTransactions(investmentId, { pageSize: MAX_PAGE_SIZE });
            if (totalPages === 1) {
                return firstPageResults;
            }
            const transactions = [...firstPageResults];
            let page = 1;
            while (page < totalPages) {
                page++;
                const paginatedTransactions = yield this.fetchInvestmentTransactions(investmentId, {
                    page,
                    pageSize: MAX_PAGE_SIZE,
                });
                transactions.push(...paginatedTransactions.results);
            }
            return transactions;
        });
    }
    /**
     * Fetch loans from an Item
     *
     * @param {string} itemId
     * @param {PageFilters} options - request search filters
     * @returns {Promise<PageResponse<Loan>>} - paged response of loans
     */
    fetchLoans(itemId, options = {}) {
        return __awaiter(this, void 0, void 0, function* () {
            return yield this.createGetRequest('loans', Object.assign(Object.assign({}, options), { itemId }));
        });
    }
    /**
     * Fetch loan by id
     *
     * @param {string} id - the loan id
     * @returns {Promise<Loan>} - loan object, if found
     */
    fetchLoan(id) {
        return __awaiter(this, void 0, void 0, function* () {
            return yield this.createGetRequest(`loans/${id}`);
        });
    }
    /**
     * Fetch consents from an Item
     *
     * @param {string} itemId - the item id
     * @param {ConsentFilters} options - request search filters
     * @returns {Promise<PageResponse<Consent>>} - paged response of consents
     */
    fetchConsents(itemId, options = {}) {
        return __awaiter(this, void 0, void 0, function* () {
            return yield this.createGetRequest('consents', Object.assign(Object.assign({}, options), { itemId }));
        });
    }
    /**
     * Fetch consent by id
     *
     * @param {string} id - the consent id
     * @returns {Promise<Consent>} - consent object, if found
     */
    fetchConsent(id) {
        return __awaiter(this, void 0, void 0, function* () {
            return yield this.createGetRequest(`consents/${id}`);
        });
    }
    /**
     * Fetch the identity resource
     * @returns {IdentityResponse} an identity object
     */
    fetchIdentity(id) {
        return __awaiter(this, void 0, void 0, function* () {
            return yield this.createGetRequest(`identity/${id}`);
        });
    }
    /**
     * Fetch the identity resource by it's Item ID
     * @returns {IdentityResponse} an identity object
     */
    fetchIdentityByItemId(itemId) {
        return __awaiter(this, void 0, void 0, function* () {
            return yield this.createGetRequest(`identity?itemId=${itemId}`);
        });
    }
    /**
     * Fetch credit card bills from an accountId
     * @returns {PageResponse<CreditCardBills>} an credit card bills object
     */
    fetchCreditCardBills(accountId, options = {}) {
        return __awaiter(this, void 0, void 0, function* () {
            return yield this.createGetRequest('bills', Object.assign(Object.assign({}, options), { accountId }));
        });
    }
    /**
     * Fetch a single credit card bill by its id
     * @param {string} id - the credit card bill id
     * @returns {Promise<CreditCardBills>} - credit card bill object, if found
     */
    fetchCreditCardBill(id) {
        return __awaiter(this, void 0, void 0, function* () {
            return yield this.createGetRequest(`bills/${id}`);
        });
    }
    /**
     * Fetch all available categories
     * @returns {Categories[]} an paging response of categories
     */
    fetchCategories() {
        return __awaiter(this, void 0, void 0, function* () {
            return yield this.createGetRequest('categories');
        });
    }
    /**
     * Fetch a single category
     * @returns {Category} a category object
     */
    fetchCategory(id) {
        return __awaiter(this, void 0, void 0, function* () {
            return yield this.createGetRequest(`categories/${id}`);
        });
    }
    /**
     * Fetch a single webhook
     * @returns {Webhook} a webhook object
     */
    fetchWebhook(id) {
        return __awaiter(this, void 0, void 0, function* () {
            return yield this.createGetRequest(`webhooks/${id}`);
        });
    }
    /**
     * Fetch all available webhooks
     * @returns {Webhook[]} a paging response of webhooks
     */
    fetchWebhooks() {
        return __awaiter(this, void 0, void 0, function* () {
            return yield this.createGetRequest('webhooks');
        });
    }
    /**
     * Creates a Webhook
     * @param webhookParams - The webhook params to create, this includes:
     * - url: The url where will receive notifications
     * - event: The event to listen for
     * - headers (optional): The headers to send with the webhook
     * @returns {Webhook} the created webhook object
     */
    createWebhook(event, url, headers) {
        return __awaiter(this, void 0, void 0, function* () {
            return yield this.createPostRequest(`webhooks`, null, {
                event,
                url,
                headers,
            });
        });
    }
    /**
     * Updates a Webhook
     * @param id - The Webhook ID
     * @param updatedWebhookParams - The webhook params to update
     * @returns {Webhook} The webhook updated
     */
    updateWebhook(id, updatedWebhookParams) {
        return __awaiter(this, void 0, void 0, function* () {
            return yield this.createPatchRequest(`webhooks/${id}`, null, updatedWebhookParams);
        });
    }
    /**
     * Deletes a Webhook
     */
    deleteWebhook(id) {
        return __awaiter(this, void 0, void 0, function* () {
            return yield this.createDeleteRequest(`webhooks/${id}`);
        });
    }
    /**
     * Creates a connect token that can be used as API KEY to connect items from the Frontend
     * @returns {string} Access token to connect items with restrict access
     */
    createConnectToken(itemId, options) {
        return __awaiter(this, void 0, void 0, function* () {
            return yield this.createPostRequest(`connect_token`, null, { itemId, options });
        });
    }
}
exports.PluggyClient = PluggyClient;
