/**
 * Prometheus metrics for extraction-service.
 *
 * Exposed via GET /metrics (auto-registered by fastify-metrics).
 * Custom counters/histograms for extraction-specific telemetry.
 */

// ── In-memory counters (fastify-metrics handles HTTP metrics) ────
// These are simple counters since prom-client may not be directly available.
// They're exposed via the /extract/metrics endpoint.

interface MetricBucket {
  labels: Record<string, string>;
  value: number;
}

class Counter {
  private _buckets = new Map<string, MetricBucket>();
  constructor(public readonly name: string) {}

  inc(labels: Record<string, string>, amount = 1): void {
    const key = JSON.stringify(labels);
    const existing = this._buckets.get(key);
    if (existing) {
      existing.value += amount;
    } else {
      this._buckets.set(key, { labels, value: amount });
    }
  }

  toJSON(): Array<{ labels: Record<string, string>; value: number }> {
    return [...this._buckets.values()];
  }
}

class Histogram {
  private _observations: Array<{ labels: Record<string, string>; value: number }> = [];
  private _sum = 0;
  private _count = 0;
  constructor(public readonly name: string) {}

  observe(labels: Record<string, string>, value: number): void {
    this._observations.push({ labels, value });
    this._sum += value;
    this._count++;
  }

  toJSON(): { count: number; sum: number; avg: number } {
    return {
      count: this._count,
      sum: Math.round(this._sum * 100) / 100,
      avg: this._count > 0 ? Math.round((this._sum / this._count) * 100) / 100 : 0,
    };
  }
}

// ── Exported metrics ─────────────────────────────────────────────

export const extractionRequestsTotal = new Counter('extraction_requests_total');
export const extractionDurationSeconds = new Histogram('extraction_duration_seconds');
export const extractionEntitiesExtracted = new Histogram('extraction_entities_extracted');
export const extractionCacheHitTotal = new Counter('extraction_cache_hit_total');

/**
 * Record an extraction event with all metric dimensions.
 */
export function recordExtraction(params: {
  taskId?: string;
  modelId?: string;
  productId?: string;
  status: 'success' | 'error' | 'cache_hit';
  durationMs?: number;
  entityCount?: number;
}): void {
  const labels = {
    task_id: params.taskId || 'unknown',
    model_id: params.modelId || 'unknown',
    product_id: params.productId || 'unknown',
    status: params.status,
  };

  extractionRequestsTotal.inc(labels);

  if (params.status === 'cache_hit') {
    extractionCacheHitTotal.inc(labels);
  }

  if (params.durationMs !== undefined) {
    extractionDurationSeconds.observe(labels, params.durationMs / 1000);
  }

  if (params.entityCount !== undefined) {
    extractionEntitiesExtracted.observe(labels, params.entityCount);
  }
}

/**
 * Get all metrics as a JSON summary.
 */
export function getMetricsSummary(): Record<string, unknown> {
  return {
    extraction_requests_total: extractionRequestsTotal.toJSON(),
    extraction_duration_seconds: extractionDurationSeconds.toJSON(),
    extraction_entities_extracted: extractionEntitiesExtracted.toJSON(),
    extraction_cache_hit_total: extractionCacheHitTotal.toJSON(),
  };
}
