/**
 * Prometheus Metrics for Audit Log System
 * Phase A: Basic metrics for monitoring and alerting
 */

import { Registry, Counter, Histogram, Gauge } from 'prom-client';
import { AuditOutbox } from '#models/AuditOutbox';

// Create a separate registry for audit metrics
export const auditRegistry = new Registry();

// Counter: Total audit events enqueued
export const auditEventsEnqueued = new Counter({
	name: 'audit_events_enqueued_total',
	help: 'Total number of audit events enqueued to outbox',
	labelNames: ['event_type', 'module'],
	registers: [auditRegistry],
});

// Counter: Total audit events processed
export const auditEventsProcessed = new Counter({
	name: 'audit_events_processed_total',
	help: 'Total number of audit events processed from outbox',
	labelNames: ['event_type', 'status'],
	registers: [auditRegistry],
});

// Counter: Total audit events failed
export const auditEventsFailed = new Counter({
	name: 'audit_events_failed_total',
	help: 'Total number of audit events that failed processing',
	labelNames: ['event_type', 'error_type'],
	registers: [auditRegistry],
});

// Counter: Dead letter queue events
export const auditDeadLetterEvents = new Counter({
	name: 'audit_dead_letter_events_total',
	help: 'Total number of events moved to dead letter queue',
	labelNames: ['event_type'],
	registers: [auditRegistry],
});

// Histogram: Processing time
export const auditProcessingDuration = new Histogram({
	name: 'audit_processing_duration_seconds',
	help: 'Time taken to process audit events',
	labelNames: ['event_type'],
	buckets: [0.01, 0.05, 0.1, 0.5, 1, 5, 10],
	registers: [auditRegistry],
});

// Gauge: Outbox queue size
export const auditOutboxQueueSize = new Gauge({
	name: 'audit_outbox_queue_size',
	help: 'Current number of events in outbox queue',
	labelNames: ['status'],
	registers: [auditRegistry],
});

// Gauge: Total queue depth (all events in last hour)
export const auditOutboxQueueDepth = new Gauge({
	name: 'audit_outbox_queue_depth',
	help: 'Total number of events in outbox queue in last hour',
	registers: [auditRegistry],
});

// Gauge: Pending events count
export const auditOutboxPending = new Gauge({
	name: 'audit_outbox_pending_count',
	help: 'Number of pending events in outbox queue',
	registers: [auditRegistry],
});

// Gauge: Processing events count
export const auditOutboxProcessing = new Gauge({
	name: 'audit_outbox_processing_count',
	help: 'Number of processing events in outbox queue',
	registers: [auditRegistry],
});

// Gauge: Failed events count
export const auditOutboxFailed = new Gauge({
	name: 'audit_outbox_failed_count',
	help: 'Number of failed events in outbox queue',
	registers: [auditRegistry],
});

// Counter: Audit log access
export const auditLogAccess = new Counter({
	name: 'audit_log_access_total',
	help: 'Total number of audit log access events',
	labelNames: ['action', 'user_id'],
	registers: [auditRegistry],
});

// Counter: Audit log exports
export const auditLogExports = new Counter({
	name: 'audit_log_exports_total',
	help: 'Total number of audit log exports',
	labelNames: ['format', 'record_count'],
	registers: [auditRegistry],
});

// Counter: Dead letter replays
export const auditDeadLetterReplays = new Counter({
	name: 'audit_dead_letter_replays_total',
	help: 'Total number of dead letter events replayed',
	labelNames: ['event_type', 'success'],
	registers: [auditRegistry],
});

// Helper function to update queue size gauge (optional, called manually if needed)
export async function updateOutboxQueueSize() {
	try {
		const pendingCount = await AuditOutbox.count({ where: { status: 'PENDING' } });
		const processingCount = await AuditOutbox.count({ where: { status: 'PROCESSING' } });
		const failedCount = await AuditOutbox.count({ where: { status: 'FAILED' } });

		auditOutboxQueueSize.set({ status: 'PENDING' }, pendingCount);
		auditOutboxQueueSize.set({ status: 'PROCESSING' }, processingCount);
		auditOutboxQueueSize.set({ status: 'FAILED' }, failedCount);
	} catch (error) {
		console.error('Failed to update outbox queue size metrics:', error);
	}
}

// Initialize metrics collection (call this on startup)
export function initAuditMetrics() {
	// Note: Queue depth monitoring is now handled by OutboxPoller.monitorQueueDepth()
	// which runs on every batch process. This function is kept for backward compatibility.
	// If you want to enable interval-based updates, uncomment the line below:
	// setInterval(updateOutboxQueueSize, 30000);
}

export default {
	auditRegistry,
	auditEventsEnqueued,
	auditEventsProcessed,
	auditEventsFailed,
	auditDeadLetterEvents,
	auditProcessingDuration,
	auditOutboxQueueSize,
	auditOutboxQueueDepth,
	auditOutboxPending,
	auditOutboxProcessing,
	auditOutboxFailed,
	auditLogAccess,
	auditLogExports,
	auditDeadLetterReplays,
	updateOutboxQueueSize,
	initAuditMetrics,
};
