import { GenericValue, IDataObject, IExecuteFunctions, IHookFunctions, IHttpRequestMethods, IHttpRequestOptions, ILoadOptionsFunctions, IN8nHttpResponse } from "n8n-workflow";
import { prettyLog } from "./pretty-log";
import { THttpFullResponse } from "@src/types/httpRequest";


type TBody = FormData | GenericValue | GenericValue[] | Buffer | URLSearchParams;
type TQueryString = IDataObject;

// class ApiCall
//     get( path: string, options?: { params?: TQueryString, verbose?: boolean })
//     post( path: string, options?: { body: TBody, verbose?: boolean } )
//     put( path: string, options?: { body: TBody, verbose?: boolean })
//     delete( path: string, options?: { body: TBody, verbose?: boolean })

export class ApiCall {
    private n8n: IExecuteFunctions | ILoadOptionsFunctions | IHookFunctions
    private baseURL: string

    constructor(executeFunction: IExecuteFunctions | ILoadOptionsFunctions | IHookFunctions, baseURL: string) {
        this.n8n = executeFunction
        this.baseURL = baseURL
    }

    private async httpRequestWithAuthentication<T extends IN8nHttpResponse>({ method, path, body, params, verbose = false }: {
        method: IHttpRequestMethods, path: string, body?: TBody, params?: TQueryString, verbose?: boolean;
    }) {
        const url = path.startsWith('/') ? `${this.baseURL}${path}` : path;

        const options: IHttpRequestOptions = {
            method,
            body,
            headers: {
                'Content-Type': 'application/json',
                'Version': '2021-07-28',
            },
            qs: params,
            url: url,
            returnFullResponse: true
        };

        if (verbose) {
            console.log(`curl -X ${method} ${url}\n${body ? ` -d '${JSON.stringify(body, null, 2)}'` : ''}`);
            prettyLog(options);
        }

        const response = (await this.n8n.helpers.httpRequestWithAuthentication.call(this.n8n, 'goHighLevelOAuth2Api', options)) as THttpFullResponse<T>;

        if (verbose) {
            prettyLog({
                infos: {
                    statusCode: response.statusCode,
                    statusMessage: response.statusMessage,
                },
                body: response.body,
            });
        }

        return response;
    }

    async get<T extends IN8nHttpResponse>(path: string, options?: { params?: TQueryString, verbose?: boolean }) {
        const response = await this.httpRequestWithAuthentication<T>({
            method: 'GET',
            path,
            ...options,
            verbose: false
        });

        return response.body;
    }

    async post<T extends IN8nHttpResponse>(path: string, options?: { body: TBody, verbose?: boolean }) {
        const response = await this.httpRequestWithAuthentication<T>({
            method: 'POST',
            path,
            ...options,
        });

        return response.body;
    }

    async put<T extends IN8nHttpResponse>(path: string, options?: { body: TBody, verbose?: boolean }) {
        const response = await this.httpRequestWithAuthentication<T>({
            method: 'PUT',
            path,
            ...options,
            verbose: true,
        });

        return response.body;
    }

    async delete<T extends IN8nHttpResponse>(path: string, options?: { body: TBody, verbose?: boolean }) {
        const response = await this.httpRequestWithAuthentication<T>({
            method: 'DELETE',
            path,
            ...options,
        });

        return response.body;
    }
}

export default ApiCall
