// @ts-check

/**
 * Imports
 * ==============================================================================
 */
const https = require("https");
const http = require("http");
const { URL } = require("url");

//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////

/**
 * Main Function
 * ==============================================================================
 * @param {{
 *  scheme?: string,
 *  url?: string,
 *  method?: string,
 *  hostname?: string,
 *  path?: string,
 *  port?: number | string,
 *  headers?: object,
 *  body?: object,
 * }} params - params
 */
module.exports = function httpsRequest({
    url,
    method,
    hostname,
    path,
    headers,
    body,
    port,
    scheme,
}) {
    const reqPayloadString = body ? JSON.stringify(body) : null;

    const PARSED_URL = url ? new URL(url) : null;

    ////////////////////////////////////////////////
    ////////////////////////////////////////////////
    ////////////////////////////////////////////////

    /** @type {any} */
    let requestOptions = {
        method: method || "GET",
        hostname: PARSED_URL ? PARSED_URL.hostname : hostname,
        port: scheme?.match(/https/i)
            ? 443
            : PARSED_URL
            ? PARSED_URL.protocol?.match(/https/i)
                ? 443
                : PARSED_URL.port
            : port
            ? Number(port)
            : 80,
        headers: {},
    };

    if (path) requestOptions.path = path;
    // if (href) requestOptions.href = href;

    if (headers) requestOptions.headers = headers;
    if (body) {
        requestOptions.headers["Content-Type"] = "application/json";
        requestOptions.headers["Content-Length"] = reqPayloadString
            ? Buffer.from(reqPayloadString).length
            : undefined;
    }

    ////////////////////////////////////////////////
    ////////////////////////////////////////////////
    ////////////////////////////////////////////////

    return new Promise((res, rej) => {
        const httpsRequest = (
            scheme?.match(/https/i)
                ? https
                : PARSED_URL?.protocol?.match(/https/i)
                ? https
                : http
        ).request(
            /* ====== Request Options object ====== */
            requestOptions,

            ////////////////////////////////////////////////
            ////////////////////////////////////////////////
            ////////////////////////////////////////////////

            /* ====== Callback function ====== */
            (response) => {
                var str = "";

                // ## another chunk of data has been received, so append it to `str`
                response.on("data", function (chunk) {
                    str += chunk;
                });

                // ## the whole response has been received, so we just print it out here
                response.on("end", function () {
                    res(str);
                });

                response.on("error", (error) => {
                    console.log("HTTP response error =>", error.message);
                    rej(`HTTP response error =>, ${error.message}`);
                });

                response.on("close", () => {
                    console.log("HTTP(S) Response Closed Successfully");
                });
            }
        );

        if (body) httpsRequest.write(reqPayloadString);

        httpsRequest.on("error", (error) => {
            console.log("HTTPS request ERROR =>", error.message);
            rej(`HTTP request error =>, ${error.message}`);
        });

        httpsRequest.end();

        ////////////////////////////////////////////////
        ////////////////////////////////////////////////
        ////////////////////////////////////////////////
    });
};

//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////