// ABOUTME: BullMQ worker for the dead letter queue - logs/audits jobs that exhausted all retries
// ABOUTME: Provides a durable audit trail for operators to inspect, replay, or alert on failures

import { Worker, Job } from 'bullmq';
import logger from '../utils/logger';
import { connection, QUEUE_NAMES } from './queue';

// ============================================================================
// Types
// ============================================================================

export interface DeadLetterJobData {
  /** Original job data (including any custom fields from the source queue) */
  [key: string]: unknown;
  /** Error message that caused the final failure */
  _failedReason: string;
  /** Name of the source queue (e.g. "morning-scrape", "pre-race") */
  _sourceQueue: string;
  /** ISO timestamp when the job was moved to the dead letter queue */
  _failedAt: string;
  /** Original BullMQ job ID from the source queue */
  _originalJobId: string;
  /** Optional stack trace from the final failure */
  _stackTrace?: string;
  /** Number of attempts made before exhaustion */
  _attemptsMade?: number;
}

// ============================================================================
// Worker Factory
// ============================================================================

export function createDeadLetterWorker(): Worker {
  const worker = new Worker<DeadLetterJobData>(
    QUEUE_NAMES.DEAD_LETTER,
    async (job: Job<DeadLetterJobData>) => {
      const {
        _failedReason,
        _sourceQueue,
        _failedAt,
        _originalJobId,
        _stackTrace,
        _attemptsMade,
        ...originalData
      } = job.data;

      logger.warn(
        {
          msg: 'Dead letter job received',
          deadLetterJobId: job.id,
          originalJobId: _originalJobId,
          sourceQueue: _sourceQueue,
          failedReason: _failedReason,
          failedAt: _failedAt,
          attemptsMade: _attemptsMade,
          // Log a summary of the original data (avoid dumping huge payloads)
          originalDataKeys: Object.keys(originalData),
        },
        'Dead letter queue: job received for auditing'
      );

      // Here you could also:
      // - Send an alert (email, Slack, PagerDuty, etc.)
      // - Write to a database table for durable audit
      // - Trigger a manual review workflow
      // - Automatically retry under certain conditions

      return { processed: true, originalJobId: _originalJobId, sourceQueue: _sourceQueue };
    },
    {
      connection,
      concurrency: 5, // Process multiple dead letter jobs concurrently
      lockDuration: 30_000,
    }
  );

  worker.on('completed', (job: Job) => {
    logger.info(
      { jobId: job.id, queue: QUEUE_NAMES.DEAD_LETTER },
      'Dead letter worker: job completed'
    );
  });

  worker.on('failed', (job: Job | undefined, error: Error) => {
    logger.error(
      {
        jobId: job?.id,
        queue: QUEUE_NAMES.DEAD_LETTER,
        error: error.message,
      },
      'Dead letter worker: job failed'
    );
  });

  // Log when the worker starts/stops (useful for operator visibility)
  worker.on('active', (job: Job) => {
    logger.debug(
      { jobId: job.id, queue: QUEUE_NAMES.DEAD_LETTER },
      'Dead letter worker: processing job'
    );
  });

  logger.info('Dead letter worker created');
  return worker;
}
