import { Injectable, OnModuleInit } from '@nestjs/common';
import { Registry, Gauge, Counter, Histogram, collectDefaultMetrics } from 'prom-client';

@Injectable()
export class MetricsService implements OnModuleInit {
  private readonly registry: Registry;

  // ============ Gauges (当前值) ============

  /** 当前在线人数 */
  public readonly onlineUsersGauge: Gauge<string>;

  /** 今日 DAU */
  public readonly dauGauge: Gauge<string>;

  /** 事件队列待处理数 */
  public readonly eventQueueSizeGauge: Gauge<string>;

  // ============ Counters (累计值) ============

  /** 心跳总数 */
  public readonly heartbeatTotal: Counter<string>;

  /** 事件上报总数 */
  public readonly eventsReceivedTotal: Counter<string>;

  /** 会话开始总数 */
  public readonly sessionStartTotal: Counter<string>;

  /** 会话结束总数 */
  public readonly sessionEndTotal: Counter<string>;

  // ============ Histograms (分布) ============

  /** 心跳处理时间 */
  public readonly heartbeatDuration: Histogram<string>;

  /** 事件批量上传处理时间 */
  public readonly eventBatchDuration: Histogram<string>;

  constructor() {
    this.registry = new Registry();

    // 默认指标 (CPU, 内存, GC 等)
    collectDefaultMetrics({ register: this.registry, prefix: 'presence_' });

    // ============ 定义 Gauges ============

    this.onlineUsersGauge = new Gauge({
      name: 'presence_online_users_total',
      help: 'Current number of online users',
      registers: [this.registry],
    });

    this.dauGauge = new Gauge({
      name: 'presence_dau_total',
      help: 'Daily Active Users count',
      labelNames: ['date'],
      registers: [this.registry],
    });

    this.eventQueueSizeGauge = new Gauge({
      name: 'presence_event_queue_size',
      help: 'Number of events pending in queue',
      registers: [this.registry],
    });

    // ============ 定义 Counters ============

    this.heartbeatTotal = new Counter({
      name: 'presence_heartbeat_total',
      help: 'Total number of heartbeats received',
      labelNames: ['app_version'],
      registers: [this.registry],
    });

    this.eventsReceivedTotal = new Counter({
      name: 'presence_events_received_total',
      help: 'Total number of telemetry events received',
      labelNames: ['event_name'],
      registers: [this.registry],
    });

    this.sessionStartTotal = new Counter({
      name: 'presence_session_start_total',
      help: 'Total number of session starts (for DAU)',
      registers: [this.registry],
    });

    this.sessionEndTotal = new Counter({
      name: 'presence_session_end_total',
      help: 'Total number of session ends',
      registers: [this.registry],
    });

    // ============ 定义 Histograms ============

    this.heartbeatDuration = new Histogram({
      name: 'presence_heartbeat_duration_seconds',
      help: 'Heartbeat processing duration in seconds',
      buckets: [0.001, 0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1],
      registers: [this.registry],
    });

    this.eventBatchDuration = new Histogram({
      name: 'presence_event_batch_duration_seconds',
      help: 'Event batch processing duration in seconds',
      buckets: [0.01, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5],
      registers: [this.registry],
    });
  }

  onModuleInit() {
    // 初始化时可以加载一些初始值
  }

  /** 获取 Prometheus 格式的指标 */
  async getMetrics(): Promise<string> {
    return this.registry.metrics();
  }

  /** 获取 Content-Type */
  getContentType(): string {
    return this.registry.contentType;
  }

  // ============ 便捷方法 ============

  /** 更新在线人数 */
  setOnlineUsers(count: number): void {
    this.onlineUsersGauge.set(count);
  }

  /** 更新 DAU */
  setDau(date: string, count: number): void {
    this.dauGauge.labels(date).set(count);
  }

  /** 记录心跳 */
  recordHeartbeat(appVersion: string, durationSeconds: number): void {
    this.heartbeatTotal.labels(appVersion).inc();
    this.heartbeatDuration.observe(durationSeconds);
  }

  /** 记录事件 */
  recordEvent(eventName: string): void {
    this.eventsReceivedTotal.labels(eventName).inc();

    // 特殊处理会话事件
    if (eventName === 'app_session_start') {
      this.sessionStartTotal.inc();
    } else if (eventName === 'app_session_end') {
      this.sessionEndTotal.inc();
    }
  }

  /** 记录批量事件处理时间 */
  recordEventBatchDuration(durationSeconds: number): void {
    this.eventBatchDuration.observe(durationSeconds);
  }
}
