import { LogQL, StreamSelector } from '@sigyn/logql';
import { LokiPatternType, LokiLiteralPattern } from '@sigyn/pattern';

type ApiCredentialAuthorizationOptions = {
    type: "bearer";
    token: string;
} | {
    type: "classic";
    username: string;
    password: string;
} | {
    type: "custom";
    authorization: string;
};
declare class ApiCredential {
    private authorization;
    private userAgent;
    static buildAuthorizationHeader(authorizationOptions: ApiCredentialAuthorizationOptions): string;
    constructor(authorizationOptions?: ApiCredentialAuthorizationOptions, userAgent?: string);
    get httpOptions(): {
        headers: {
            "User-Agent"?: string | undefined;
            authorization?: string | undefined;
        };
    };
}

interface Datasource {
    id: number;
    uid: string;
    orgId: number;
    name: string;
    type: string;
    typeName?: string;
    typeLogoUrl: string;
    access: string;
    url: string;
    password?: string;
    user: string;
    database: string;
    basicAuth: boolean;
    basicAuthUser?: string;
    basicAuthPassword?: string;
    withCredentials?: boolean;
    isDefault: boolean;
    jsonData?: {
        authType?: string;
        defaultRegion?: string;
        logLevelField?: string;
        logMessageField?: string;
        timeField?: string;
        maxConcurrentShardRequests?: number;
        maxLines?: number;
        graphiteVersion?: string;
        graphiteType?: string;
    };
    secureJsonFields?: {
        basicAuthPassword?: boolean;
    };
    version?: number;
    readOnly: boolean;
}
declare class Datasources {
    private remoteApiURL;
    private credential;
    constructor(remoteApiURL: URL, credential: ApiCredential);
    all(): Promise<Datasource[]>;
    byId(id: string | number): Promise<Datasource>;
    byName(name: string): Promise<Datasource>;
    byUID(uid: string): Promise<Datasource>;
    idByName(name: string): Promise<number>;
}

type TimeRange = [first: number, last: number];

type LokiStandardBaseResponse<S> = {
    status: "failed";
} | {
    status: "success";
    data: S;
};
interface LokiQueryRangeStats {
    summary: {
        bytesProcessedPerSecond: number;
        linesProcessedPerSecond: number;
        totalBytesProcessed: number;
        totalLinesProcessed: number;
        execTime: number;
    };
    store: {
        totalChunksRef: number;
        totalChunksDownloaded: number;
        chunksDownloadTime: number;
        headChunkBytes: number;
        headChunkLines: number;
        decompressedBytes: number;
        decompressedLines: number;
        compressedBytes: number;
        totalDuplicates: number;
    };
    ingester: {
        totalReached: number;
        totalChunksMatched: number;
        totalBatches: number;
        totalLinesSent: number;
        headChunkBytes: number;
        headChunkLines: number;
        decompressedBytes: number;
        decompressedLines: number;
        compressedBytes: number;
        totalDuplicates: number;
    };
}
interface RawQueryRangeTemplate<Type extends "matrix" | "streams" | "vector", Result extends LokiMatrix[] | LokiVector | LokiStream[]> {
    status: "success";
    data: {
        resultType: Type;
        result: Result;
        stats: LokiQueryRangeStats;
    };
}
type RawQueryRangeResponse<T extends "matrix" | "streams" | "vector"> = T extends "matrix" ? RawQueryRangeTemplate<T, LokiMatrix[]> : T extends "streams" ? RawQueryRangeTemplate<T, LokiStream[]> : RawQueryRangeTemplate<T, LokiVector>;
type LokiLabels = Record<string, string>;
interface LokiVector {
    metric: LokiLabels;
    values: [unixEpoch: number, metric: string];
}
interface LokiStream<T = string> {
    stream: LokiLabels;
    values: [unixEpoch: number, log: T][];
}
interface LokiMatrix {
    metric: LokiLabels;
    values: [unixEpoch: number, metric: string][];
}
interface LokiCombined<T = string> {
    labels: LokiLabels;
    values: [unixEpoch: number, log: T][];
}
interface QueryRangeLogsResponse<T extends LokiPatternType> {
    logs: LokiLiteralPattern<T>[];
    timerange: TimeRange | null;
}
interface QueryRangeStreamResponse<T extends LokiPatternType> {
    streams: LokiCombined<LokiLiteralPattern<T>>[];
    timerange: TimeRange | null;
}
interface QueryRangeMatrixResponse {
    metrics: LokiCombined<string>[];
    timerange: TimeRange | null;
}

type LogEntry = [unixEpoch: string, log: string];
type LogEntryWithMetadata = [unixEpoch: string, log: string, metadata: Record<string, string>];
interface LokiIngestLogs {
    stream: Record<string, string | number | boolean>;
    values: (LogEntry | LogEntryWithMetadata)[];
}

interface LokiQueryOptions {
    /**
     * @default 100
     */
    limit?: number;
    start?: number | string;
    end?: number | string;
    since?: string;
}
interface LokiQueryStreamOptions<T extends LokiPatternType> extends LokiQueryOptions {
    pattern?: T;
}
interface LokiLabelsOptions {
    /**
     * The start time for the query as
     * - a nanosecond Unix epoch.
     * - a duration (i.e "2h")
     *
     * Default to 6 hours ago.
     */
    start?: number | string;
    /**
     * The end time for the query as
     * - a nanosecond Unix epoch.
     * - a duration (i.e "2h")
     *
     * Default to now
     */
    end?: number | string;
    /**
     * A duration used to calculate start relative to end. If end is in the future, start is calculated as this duration before now.
     *
     * Any value specified for start supersedes this parameter.
     */
    since?: string;
}
interface LokiLabelValuesOptions extends LokiLabelsOptions {
    /**
     * A set of log stream selector that selects the streams to match and return label values for <name>.
     *
     * Example: {"app": "myapp", "environment": "dev"}
     */
    query?: string;
}
declare class Loki {
    #private;
    private remoteApiURL;
    private credential;
    constructor(remoteApiURL: URL, credential: ApiCredential);
    queryRangeMatrix(logQL: LogQL | string, options?: LokiQueryOptions): Promise<QueryRangeMatrixResponse>;
    queryRangeStream<T extends LokiPatternType = string>(logQL: LogQL | string, options?: LokiQueryStreamOptions<T>): Promise<QueryRangeStreamResponse<T>>;
    queryRange<T extends LokiPatternType = string>(logQL: LogQL | string, options?: LokiQueryStreamOptions<T>): Promise<QueryRangeLogsResponse<T>>;
    labels(options?: LokiLabelsOptions): Promise<string[]>;
    labelValues(label: string, options?: LokiLabelValuesOptions): Promise<string[]>;
    series<T = Record<string, string>>(...match: [StreamSelector | string, ...(StreamSelector | string)[]]): Promise<T[]>;
    push(logs: Iterable<LokiIngestLogs>): Promise<void>;
}

interface GrafanaApiOptions {
    /**
     * If omitted then no authorization is dispatched to requests
     */
    authentication?: ApiCredentialAuthorizationOptions;
    /**
     * User-agent HTTP header to forward to Grafana/Loki API
     * @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agents
     */
    userAgent?: string;
    /**
     * Remote Grafana root API URL
     */
    remoteApiURL: string | URL;
}
declare class GrafanaApi {
    private remoteApiURL;
    private credential;
    Datasources: Datasources;
    Loki: Loki;
    constructor(options: GrafanaApiOptions);
}

export { type ApiCredentialAuthorizationOptions, type Datasource, GrafanaApi, type GrafanaApiOptions, type LogEntry, type LogEntryWithMetadata, type LokiCombined, type LokiIngestLogs, type LokiLabelValuesOptions, type LokiLabels, type LokiLabelsOptions, type LokiMatrix, type LokiQueryOptions, type LokiQueryRangeStats, type LokiStandardBaseResponse, type LokiStream, type LokiVector, type QueryRangeLogsResponse, type QueryRangeMatrixResponse, type QueryRangeStreamResponse, type RawQueryRangeResponse, type TimeRange };
