import { Gauge as PromGauge, type GaugeConfiguration } from 'prom-client';

/**
 * A wrapped instance of prom-client's Gauge, overriding some of its methods for enhanced functionality and type-safety.
 */
export type Gauge<T extends string = string> = {
    gauge: PromGauge<T>;
    labels: (labels: Record<T, string | number>) => PromGauge.Internal<T>;
    reset: () => void;
    set: (value: number) => void;
};

export const createGauge = <T extends string>(
    options: GaugeConfiguration<T>,
): Gauge<T> => {
    /**
     * The underlying instance of prom-client's Gauge.
     */
    const gauge = new PromGauge(options);

    /**
     * Applies given labels to the gauge. Labels are key-value pairs.
     * This method wraps the original Gauge's labels method for additional type-safety, requiring all configured labels to be specified.
     *
     * @param labels - An object where keys are label names and values are the label values.
     * @returns The Gauge instance with the applied labels, allowing for method chaining.
     */
    // eslint-disable-next-line @typescript-eslint/no-shadow
    const labels = (labels: Record<T, string | number>) => gauge.labels(labels);

    /**
     * Resets the gauge value.
     * Wraps the original Gauge's reset method.
     */
    const reset = () => gauge.reset();

    /**
     * Sets the gauge to a specified value.
     * Wraps the original Gauge's set method.
     *
     * @param value - The value to set the gauge to.
     */
    const set = (value: number) => gauge.set(value);

    return {
        gauge,
        labels,
        reset,
        set,
    };
};
