/* tslint:disable */
/* eslint-disable */
/**
 * Paystack
 * The OpenAPI specification of the Paystack API that merchants and developers can harness to build financial solutions in Africa.
 *
 * The version of the Paystack Node library: 1.0.0
 * Contact: techsupport@paystack.com
 *
 * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
 * https://openapi-generator.tech
 * Do not edit the class manually.
 */


import https = require('https');

const BASE_PATH = "https://api.paystack.co".replace(/\/+$/, "");
type HTTPMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'OPTIONS' | 'HEAD';
type HTTPHeaders = { [key: string]: string };
type HTTPBody = any
type HTTPQuery = { [key: string]: string | number | null | boolean | Array<string | number | null | boolean> | HTTPQuery };

interface Request {
    path: string;
    method: HTTPMethod;
    headers?: HTTPHeaders;
    body?: HTTPBody;
    query?: HTTPQuery
}

/**
 * This is the base class for all generated API classes.
 */
export class BaseAPI {
    constructor(readonly apiKey: string) {}

    protected async request(params: Request): Promise<Response> {
        // TODO: Do checks on params
        const response = await this.makeRequest(params);

        // if (response.status >= 200 && response.status < 300) {
        //     return response;
        // }
        // throw response;

        return response
    }

    private makeRequest(request: Request): Promise<Response> {
        const query = this.parseQueryParams(request.query)
        const tempPath = query.length === 0 ? request.path : `${request.path}?${query}`
        const options = {
            method: request.method,
            path: tempPath,
            headers: {
                "authorization": `Bearer ${this.apiKey}`,
                "user-agent": `@paystack/paystack-sdk - 1.0.1`
            }
        }

        return new Promise((resolve, reject) => {
            const req = https.request(BASE_PATH, options, (res) => {

                let data: any[] = [];
              
                res.on('data', (chunk) => {
                  data.push(chunk)
                });

                res.on('end', () => {
                    try {
                        resolve(JSON.parse(Buffer.concat(data).toString()));
                    } catch(e) {
                        reject(e);
                    }
                })
            });
              
            req.on('error', (e) => {
                reject(e)
            });

            if(request.body && Object.keys(request.body).length > 0) {
                req.write(JSON.stringify(request.body))
            }

            req.end();
        })
    }

    private parseQueryParams(queryParameters: any): string {
        if(queryParameters && Object.keys(queryParameters).length === 0) {
            return ""
        }

        return new URLSearchParams(queryParameters).toString()
    }
};

export class RequiredError extends Error {
    name: "RequiredError" = "RequiredError";
    constructor(public field: string, msg?: string) {
        super(msg);
    }
}

export function exists(json: any, key: string) {
    const value = json[key];
    return value !== null && value !== undefined;
}

export function mapValues(data: any, fn: (item: any) => any) {
  return Object.keys(data).reduce(
    (acc, key) => ({ ...acc, [key]: fn(data[key]) }),
    {}
  );
}
