// AS4 Settlement Metrics Service
// Exposes Prometheus metrics for AS4 Settlement

import { logger } from './logger';

export interface As4Metrics {
  // Message Processing
  messagesReceived: number;
  messagesProcessed: number;
  messagesFailed: number;
  messageLatencyP50: number;
  messageLatencyP99: number;

  // Instructions
  instructionsReceived: number;
  instructionsAccepted: number;
  instructionsRejected: number;
  instructionsPosted: number;
  instructionsQueued: number;

  // Members
  activeMembers: number;
  totalMembers: number;

  // Certificates
  certificatesExpiringSoon: number;
  certificatesExpired: number;

  // System
  databaseConnected: number;
  redisConnected: number;
  systemUptime: number;
}

export class As4MetricsService {
  private metrics: As4Metrics = {
    messagesReceived: 0,
    messagesProcessed: 0,
    messagesFailed: 0,
    messageLatencyP50: 0,
    messageLatencyP99: 0,
    instructionsReceived: 0,
    instructionsAccepted: 0,
    instructionsRejected: 0,
    instructionsPosted: 0,
    instructionsQueued: 0,
    activeMembers: 0,
    totalMembers: 0,
    certificatesExpiringSoon: 0,
    certificatesExpired: 0,
    databaseConnected: 0,
    redisConnected: 0,
    systemUptime: 0,
  };

  /**
   * Increment message received counter
   */
  incrementMessagesReceived(): void {
    this.metrics.messagesReceived++;
  }

  /**
   * Increment message processed counter
   */
  incrementMessagesProcessed(): void {
    this.metrics.messagesProcessed++;
  }

  /**
   * Increment message failed counter
   */
  incrementMessagesFailed(): void {
    this.metrics.messagesFailed++;
  }

  /**
   * Record message latency
   */
  recordMessageLatency(latencyMs: number): void {
    // TODO: Implement proper percentile calculation
    // For now, simple average
    this.metrics.messageLatencyP99 = latencyMs;
  }

  /**
   * Increment instruction received
   */
  incrementInstructionsReceived(): void {
    this.metrics.instructionsReceived++;
  }

  /**
   * Increment instruction accepted
   */
  incrementInstructionsAccepted(): void {
    this.metrics.instructionsAccepted++;
  }

  /**
   * Increment instruction rejected
   */
  incrementInstructionsRejected(): void {
    this.metrics.instructionsRejected++;
  }

  /**
   * Increment instruction posted
   */
  incrementInstructionsPosted(): void {
    this.metrics.instructionsPosted++;
  }

  /**
   * Set instruction queue length
   */
  setInstructionsQueued(count: number): void {
    this.metrics.instructionsQueued = count;
  }

  /**
   * Update member counts
   */
  updateMemberCounts(active: number, total: number): void {
    this.metrics.activeMembers = active;
    this.metrics.totalMembers = total;
  }

  /**
   * Update certificate expiration counts
   */
  updateCertificateCounts(expiringSoon: number, expired: number): void {
    this.metrics.certificatesExpiringSoon = expiringSoon;
    this.metrics.certificatesExpired = expired;
  }

  /**
   * Update connection status
   */
  updateConnectionStatus(database: number, redis: number): void {
    this.metrics.databaseConnected = database;
    this.metrics.redisConnected = redis;
  }

  /**
   * Get current metrics
   */
  getMetrics(): As4Metrics {
    return { ...this.metrics };
  }

  /**
   * Export metrics in Prometheus format
   */
  exportPrometheusFormat(): string {
    const lines: string[] = [];

    // Message metrics
    lines.push(`# HELP as4_messages_received_total Total messages received`);
    lines.push(`# TYPE as4_messages_received_total counter`);
    lines.push(`as4_messages_received_total ${this.metrics.messagesReceived}`);

    lines.push(`# HELP as4_messages_processed_total Total messages processed`);
    lines.push(`# TYPE as4_messages_processed_total counter`);
    lines.push(`as4_messages_processed_total ${this.metrics.messagesProcessed}`);

    lines.push(`# HELP as4_messages_failed_total Total messages failed`);
    lines.push(`# TYPE as4_messages_failed_total counter`);
    lines.push(`as4_messages_failed_total ${this.metrics.messagesFailed}`);

    lines.push(`# HELP as4_message_latency_p99 Message processing latency (P99) in seconds`);
    lines.push(`# TYPE as4_message_latency_p99 gauge`);
    lines.push(`as4_message_latency_p99 ${this.metrics.messageLatencyP99 / 1000}`);

    // Instruction metrics
    lines.push(`# HELP as4_instructions_received_total Total instructions received`);
    lines.push(`# TYPE as4_instructions_received_total counter`);
    lines.push(`as4_instructions_received_total ${this.metrics.instructionsReceived}`);

    lines.push(`# HELP as4_instructions_accepted_total Total instructions accepted`);
    lines.push(`# TYPE as4_instructions_accepted_total counter`);
    lines.push(`as4_instructions_accepted_total ${this.metrics.instructionsAccepted}`);

    lines.push(`# HELP as4_instructions_rejected_total Total instructions rejected`);
    lines.push(`# TYPE as4_instructions_rejected_total counter`);
    lines.push(`as4_instructions_rejected_total ${this.metrics.instructionsRejected}`);

    lines.push(`# HELP as4_instructions_posted_total Total instructions posted`);
    lines.push(`# TYPE as4_instructions_posted_total counter`);
    lines.push(`as4_instructions_posted_total ${this.metrics.instructionsPosted}`);

    lines.push(`# HELP as4_instructions_queued Current instruction queue length`);
    lines.push(`# TYPE as4_instructions_queued gauge`);
    lines.push(`as4_instructions_queued ${this.metrics.instructionsQueued}`);

    // Member metrics
    lines.push(`# HELP as4_members_active Current active members`);
    lines.push(`# TYPE as4_members_active gauge`);
    lines.push(`as4_members_active ${this.metrics.activeMembers}`);

    lines.push(`# HELP as4_members_total Total members`);
    lines.push(`# TYPE as4_members_total gauge`);
    lines.push(`as4_members_total ${this.metrics.totalMembers}`);

    // Certificate metrics
    lines.push(`# HELP as4_certificates_expiring_soon Certificates expiring within 30 days`);
    lines.push(`# TYPE as4_certificates_expiring_soon gauge`);
    lines.push(`as4_certificates_expiring_soon ${this.metrics.certificatesExpiringSoon}`);

    lines.push(`# HELP as4_certificates_expired Expired certificates`);
    lines.push(`# TYPE as4_certificates_expired gauge`);
    lines.push(`as4_certificates_expired ${this.metrics.certificatesExpired}`);

    // Connection metrics
    lines.push(`# HELP as4_database_connection_status Database connection status (1=connected, 0=disconnected)`);
    lines.push(`# TYPE as4_database_connection_status gauge`);
    lines.push(`as4_database_connection_status ${this.metrics.databaseConnected}`);

    lines.push(`# HELP as4_redis_connection_status Redis connection status (1=connected, 0=disconnected)`);
    lines.push(`# TYPE as4_redis_connection_status gauge`);
    lines.push(`as4_redis_connection_status ${this.metrics.redisConnected}`);

    return lines.join('\n') + '\n';
  }

  /**
   * Reset metrics (for testing)
   */
  reset(): void {
    this.metrics = {
      messagesReceived: 0,
      messagesProcessed: 0,
      messagesFailed: 0,
      messageLatencyP50: 0,
      messageLatencyP99: 0,
      instructionsReceived: 0,
      instructionsAccepted: 0,
      instructionsRejected: 0,
      instructionsPosted: 0,
      instructionsQueued: 0,
      activeMembers: 0,
      totalMembers: 0,
      certificatesExpiringSoon: 0,
      certificatesExpired: 0,
      databaseConnected: 0,
      redisConnected: 0,
      systemUptime: 0,
    };
  }
}

export const as4MetricsService = new As4MetricsService();
