"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.BaseApi = void 0;
const got_1 = require("got");
const jwt = require("jsonwebtoken");
const transforms_1 = require("./transforms");
const { version: pluggyNodeVersion, dependencies: { got: gotVersion },
// eslint-disable-next-line @typescript-eslint/no-var-requires
 } = require('../package.json');
const _30_SECONDS = 30 * 1000;
class BaseApi {
    constructor(params) {
        const { clientId, clientSecret } = params;
        const { PLUGGY_API_URL } = process.env;
        this.baseUrl = PLUGGY_API_URL || 'https://api.pluggy.ai';
        if (clientSecret && clientId) {
            this.clientId = clientId;
            this.clientSecret = clientSecret;
        }
        else {
            throw new Error('Missing authorization for API communication');
        }
        this.defaultHeaders = {
            'User-Agent': `PluggyNode/${pluggyNodeVersion} node.js/${process.version.replace('v', '')} Got/${gotVersion}`,
            'Content-Type': 'application/json',
        };
    }
    getServiceInstance() {
        if (!this.serviceInstance) {
            this.serviceInstance = got_1.default.extend({
                headers: this.defaultHeaders,
                responseType: 'json',
                parseJson: transforms_1.deserializeJSONWithDates,
                timeout: _30_SECONDS,
                retry: {
                    limit: 2,
                    methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'],
                    statusCodes: [429],
                },
            });
        }
        return this.serviceInstance;
    }
    getApiKey() {
        return __awaiter(this, void 0, void 0, function* () {
            if (this.apiKey && !this.isJwtExpired(this.apiKey)) {
                return this.apiKey;
            }
            const response = yield this.getServiceInstance().post(`${this.baseUrl}/auth`, {
                json: {
                    clientId: this.clientId,
                    clientSecret: this.clientSecret,
                    nonExpiring: false,
                },
                responseType: 'json',
            });
            this.apiKey = response.body.apiKey;
            return this.apiKey;
        });
    }
    createGetRequest(endpoint, params) {
        return __awaiter(this, void 0, void 0, function* () {
            const apiKey = yield this.getApiKey();
            const url = `${this.baseUrl}/${endpoint}${this.mapToQueryString(params)}`;
            try {
                const { statusCode, body } = yield this.getServiceInstance()(url, {
                    headers: Object.assign(Object.assign({}, this.defaultHeaders), { 'X-API-KEY': apiKey }),
                    responseType: 'json',
                    parseJson: transforms_1.deserializeJSONWithDates,
                });
                if (statusCode < 200 || statusCode >= 300) {
                    return Promise.reject(body);
                }
                return body;
            }
            catch (error) {
                if (error instanceof got_1.HTTPError) {
                    console.error(`[Pluggy SDK] HTTP request failed: ${error.message || ''}`, error.response.body);
                    return Promise.reject(error.response.body);
                }
                return Promise.reject(error);
            }
        });
    }
    createPostRequest(endpoint, params, body) {
        return this.createMutationRequest('post', endpoint, params, body);
    }
    createPutRequest(endpoint, params, body) {
        return this.createMutationRequest('put', endpoint, params, body);
    }
    createPatchRequest(endpoint, params, body) {
        return this.createMutationRequest('patch', endpoint, params, body);
    }
    createDeleteRequest(endpoint, params, body) {
        return this.createMutationRequest('delete', endpoint, params, body);
    }
    createMutationRequest(method, endpoint, params, body) {
        return __awaiter(this, void 0, void 0, function* () {
            const apiKey = yield this.getApiKey();
            const url = `${this.baseUrl}/${endpoint}${this.mapToQueryString(params)}`;
            if (body) {
                Object.keys(body).forEach(key => (body[key] === undefined ? delete body[key] : {}));
            }
            try {
                const { statusCode, body: responseBody } = yield this.getServiceInstance()(url, {
                    method,
                    headers: Object.assign(Object.assign({}, this.defaultHeaders), { 'X-API-KEY': apiKey }),
                    json: body,
                });
                if (statusCode !== 200) {
                    return Promise.reject(body);
                }
                return responseBody;
            }
            catch (error) {
                if (error instanceof got_1.HTTPError) {
                    console.error(`[Pluggy SDK] HTTP request failed: ${error.message || ''}`, error.response.body);
                    return Promise.reject(error.response.body);
                }
                return Promise.reject(error);
            }
        });
    }
    mapToQueryString(params) {
        if (!params) {
            return '';
        }
        const query = Object.keys(params)
            .filter(key => params[key] !== undefined && params[key] !== null)
            .map(key => key + '=' + params[key])
            .join('&');
        return `?${query}`;
    }
    isJwtExpired(token) {
        const decoded = jwt.decode(token, { complete: true });
        return decoded.payload.exp <= Math.floor(Date.now() / 1000);
    }
}
exports.BaseApi = BaseApi;
