import { Injectable } from '@nestjs/common';

type LokiInstantQuery = {
  query: string;
  time?: string;
  limit?: number;
};

type LokiRangeQuery = {
  query: string;
  start?: string;
  end?: string;
  step?: string;
  limit?: number;
  direction?: 'forward' | 'backward';
};

@Injectable()
export class LokiClient {
  private readonly baseUrl = process.env.LOKI_BASE_URL ?? 'http://localhost:3100';
  private readonly tenantId = process.env.LOKI_TENANT_ID;
  private readonly bearerToken = process.env.LOKI_BEARER_TOKEN;

  async query(params: LokiInstantQuery): Promise<unknown> {
    const search = new URLSearchParams({ query: params.query });
    if (params.time) search.set('time', params.time);
    if (params.limit !== undefined) search.set('limit', String(params.limit));
    return this.get('/loki/api/v1/query', search);
  }

  async queryRange(params: LokiRangeQuery): Promise<unknown> {
    const search = new URLSearchParams({ query: params.query });
    if (params.start) search.set('start', params.start);
    if (params.end) search.set('end', params.end);
    if (params.step) search.set('step', params.step);
    if (params.limit !== undefined) search.set('limit', String(params.limit));
    if (params.direction) search.set('direction', params.direction);
    return this.get('/loki/api/v1/query_range', search);
  }

  private async get(path: string, search: URLSearchParams): Promise<unknown> {
    const url = new URL(path, this.baseUrl);
    url.search = search.toString();

    const headers: Record<string, string> = {};
    if (this.tenantId) {
      headers['X-Scope-OrgID'] = this.tenantId;
    }
    if (this.bearerToken) {
      headers.Authorization = `Bearer ${this.bearerToken}`;
    }

    const response = await fetch(url, { method: 'GET', headers });
    const bodyText = await response.text();

    if (!response.ok) {
      throw new Error(`Loki request failed (${response.status}): ${bodyText}`);
    }

    try {
      return JSON.parse(bodyText);
    } catch {
      return bodyText;
    }
  }
}
