import { Pushgateway, Registry, RegistryContentType } from "prom-client";
import url from "url";
import http from "http";
import https from "https";
import { gzipSync } from "zlib";

// copied mostly from pushgateway.js implementation. Just swapping out the http call to not await a response

export class FastHttpPushgateway<T extends RegistryContentType> extends Pushgateway<T> {
	constructor(url: string, options?: any, registry?: Registry<T>) {
		super(url, options, registry);
	}

  override push(params: Pushgateway.Parameters): Promise<{ resp?: unknown; body?: unknown; }> {
		let method = "PUT";
		let job = params.jobName;
		let groupings = params.groupings;
		
		// @ts-ignore
		let gatewayUrl: string = this.gatewayUrl;
		// @ts-ignore
		let requestOptions: any = this.requestOptions;

		// @ts-ignore
		let registry: Registry = this.registry;

		// `URL` first added in v6.13.0
		// eslint-disable-next-line n/no-deprecated-api
		const gatewayUrlParsed = url.parse(gatewayUrl);
		const gatewayUrlPath =
			gatewayUrlParsed.pathname && gatewayUrlParsed.pathname !== '/'
				? gatewayUrlParsed.pathname
				: '';
		const jobPath = job
			? `/job/${encodeURIComponent(job)}${generateGroupings(groupings)}`
			: '';
		const path = `${gatewayUrlPath}/metrics${jobPath}`;

		// eslint-disable-next-line n/no-deprecated-api
		const target = url.resolve(gatewayUrl, path);
		// eslint-disable-next-line n/no-deprecated-api
		const requestParams = url.parse(target);
		const httpModule = isHttps(requestParams.href) ? https : http;
		const options = Object.assign(requestParams, requestOptions, {
			method,
		});

		return new Promise((resolve, reject) => {
			if (method === 'DELETE' && options.headers) {
				delete options.headers['Content-Encoding'];
			}
			const req = httpModule.request(options);

			// write metrics
			registry
				.metrics()
				.then(metrics => {
					if (
						options.headers &&
						options.headers['Content-Encoding'] === 'gzip'
					) {
						metrics = gzipSync(metrics) as any;
					}

					// write metrics, and once thats done, end req. Don't wait for response
					req.write(metrics, () => {
						req.end(() => {
							resolve({});
						});
					});
				})
		});
	}
}

function generateGroupings(groupings: any) {
	if (!groupings) {
		return '';
	}
	return Object.keys(groupings)
		.map(
			key =>
				`/${encodeURIComponent(key)}/${encodeURIComponent(groupings[key])}`,
		)
		.join('');
}

function isHttps(href: string) {
	return href.search(/^https/) !== -1;
}
