import promClient from "prom-client";

const registry = new promClient.Registry();
// 修复：在本地 registry 上设置默认标签（原代码误用全局 register）
registry.setDefaultLabels({ service: "msg" });

// ============================================================
// HTTP 指标（02-architecture-design.md §6.4）
// ============================================================

registry.registerMetric(
  new promClient.Counter({
    name: "msg_http_requests_total",
    help: "Total number of msg HTTP requests",
    labelNames: ["method", "route", "status_code"],
  }),
);

registry.registerMetric(
  new promClient.Histogram({
    name: "msg_http_request_duration_seconds",
    help: "Msg HTTP request duration in seconds",
    labelNames: ["method", "route"],
    buckets: [0.01, 0.05, 0.1, 0.3, 0.5, 1, 3, 5],
  }),
);

// ============================================================
// gRPC 指标
// ============================================================

registry.registerMetric(
  new promClient.Counter({
    name: "msg_grpc_requests_total",
    help: "Total number of msg gRPC requests",
    labelNames: ["rpc_method", "status"],
  }),
);

// ============================================================
// 业务指标：通知发送
// ============================================================

registry.registerMetric(
  new promClient.Counter({
    name: "msg_notification_sent_total",
    help: "Total number of notifications sent",
    labelNames: ["type", "channel", "status"],
  }),
);

registry.registerMetric(
  new promClient.Histogram({
    name: "msg_notification_send_duration_seconds",
    help: "Notification send duration in seconds",
    labelNames: ["type", "channel"],
    buckets: [0.01, 0.05, 0.1, 0.3, 0.5, 1, 3, 5],
  }),
);

registry.registerMetric(
  new promClient.Counter({
    name: "msg_notification_failed_total",
    help: "Total number of notification send failures",
    labelNames: ["type", "channel", "error_code"],
  }),
);

// ============================================================
// 业务指标：通知已读
// ============================================================

registry.registerMetric(
  new promClient.Counter({
    name: "msg_notification_read_total",
    help: "Total number of notifications marked as read",
    labelNames: ["type"],
  }),
);

// ============================================================
// 业务指标：渠道分发
// ============================================================

registry.registerMetric(
  new promClient.Histogram({
    name: "msg_channel_dispatch_duration_seconds",
    help: "Channel dispatch duration in seconds",
    labelNames: ["channel"],
    buckets: [0.01, 0.05, 0.1, 0.3, 0.5, 1, 3, 5],
  }),
);

// ============================================================
// Kafka 消费指标
// ============================================================

registry.registerMetric(
  new promClient.Gauge({
    name: "msg_kafka_consumer_lag",
    help: "Kafka consumer lag (offset difference)",
    labelNames: ["topic"],
  }),
);

registry.registerMetric(
  new promClient.Counter({
    name: "msg_kafka_consumer_processed_total",
    help: "Total number of Kafka messages processed",
    labelNames: ["topic", "status"],
  }),
);

// ============================================================
// 幂等去重指标
// ============================================================

registry.registerMetric(
  new promClient.Counter({
    name: "msg_idempotent_duplicate_total",
    help: "Total number of idempotent duplicate hits",
    labelNames: ["topic"],
  }),
);

// ============================================================
// Outbox 指标
// ============================================================

registry.registerMetric(
  new promClient.Gauge({
    name: "msg_outbox_pending_count",
    help: "Number of pending outbox events",
  }),
);

// ============================================================
// Push Gateway 指标
// ============================================================

registry.registerMetric(
  new promClient.Counter({
    name: "msg_push_gateway_call_total",
    help: "Total number of Push Gateway calls",
    labelNames: ["status"],
  }),
);

registry.registerMetric(
  new promClient.Histogram({
    name: "msg_push_gateway_call_duration_seconds",
    help: "Push Gateway call duration in seconds",
    buckets: [0.01, 0.05, 0.1, 0.3, 0.5, 1, 3, 5],
  }),
);

// ============================================================
// 业务状态指标
// ============================================================

registry.registerMetric(
  new promClient.Gauge({
    name: "msg_unread_count",
    help: "User unread notification count (sampled)",
    labelNames: ["user_id"],
  }),
);

// 自动收集 Node.js 进程级指标（CPU/内存/事件循环/GC等）
// 这些指标无需业务代码埋点，prom-client 自动采集
promClient.collectDefaultMetrics({ register: registry });

// ============================================================
// 便捷访问器：业务代码通过命名导出获取已注册的 Metric 实例
// ============================================================

export const metricsRegistry = registry;

export const httpRequestsTotal = registry.getSingleMetric(
  "msg_http_requests_total",
) as promClient.Counter<string>;

export const httpRequestDurationSeconds = registry.getSingleMetric(
  "msg_http_request_duration_seconds",
) as promClient.Histogram<string>;

export const grpcRequestsTotal = registry.getSingleMetric(
  "msg_grpc_requests_total",
) as promClient.Counter<string>;

export const notificationSentTotal = registry.getSingleMetric(
  "msg_notification_sent_total",
) as promClient.Counter<string>;

export const notificationSendDurationSeconds = registry.getSingleMetric(
  "msg_notification_send_duration_seconds",
) as promClient.Histogram<string>;

export const notificationFailedTotal = registry.getSingleMetric(
  "msg_notification_failed_total",
) as promClient.Counter<string>;

export const notificationReadTotal = registry.getSingleMetric(
  "msg_notification_read_total",
) as promClient.Counter<string>;

export const channelDispatchDurationSeconds = registry.getSingleMetric(
  "msg_channel_dispatch_duration_seconds",
) as promClient.Histogram<string>;

export const kafkaConsumerLag = registry.getSingleMetric(
  "msg_kafka_consumer_lag",
) as promClient.Gauge<string>;

export const kafkaConsumerProcessedTotal = registry.getSingleMetric(
  "msg_kafka_consumer_processed_total",
) as promClient.Counter<string>;

export const idempotentDuplicateTotal = registry.getSingleMetric(
  "msg_idempotent_duplicate_total",
) as promClient.Counter<string>;

export const outboxPendingCount = registry.getSingleMetric(
  "msg_outbox_pending_count",
) as promClient.Gauge<string>;

export const pushGatewayCallTotal = registry.getSingleMetric(
  "msg_push_gateway_call_total",
) as promClient.Counter<string>;

export const pushGatewayCallDurationSeconds = registry.getSingleMetric(
  "msg_push_gateway_call_duration_seconds",
) as promClient.Histogram<string>;

export const unreadCount = registry.getSingleMetric(
  "msg_unread_count",
) as promClient.Gauge<string>;
