/**
 * Retention Job Definition
 *
 * Definiert Cleanup-Jobs für Data Retention.
 */

import { Job } from 'bullmq'
import { getQueue, QUEUE_NAMES } from '../queue-service'

// Job-Typen
export type RetentionJobType =
  | 'cleanup-collection'
  | 'cleanup-media-orphans'
  | 'retention-full'

// Job-Daten Typen
export interface RetentionJobData {
  type: RetentionJobType
  /** Collection-Slug für cleanup-collection */
  collection?: string
  /** Cutoff-Datum als ISO-String */
  cutoffDate?: string
  /** Batch-Größe für Löschung */
  batchSize?: number
  /** Feld für Datum-Vergleich */
  dateField?: string
  /** Ausgelöst von (User/System) */
  triggeredBy?: string
}

export interface RetentionJobResult {
  success: boolean
  type: RetentionJobType
  collection?: string
  deletedCount: number
  errorCount: number
  errors?: string[]
  duration: number
  timestamp: string
}

/**
 * Fügt einen Collection-Cleanup-Job zur Queue hinzu
 */
export async function enqueueCollectionCleanup(
  collection: string,
  cutoffDate: Date,
  options?: {
    batchSize?: number
    dateField?: string
    triggeredBy?: string
  }
): Promise<Job<RetentionJobData>> {
  const queue = getQueue(QUEUE_NAMES.CLEANUP)

  const data: RetentionJobData = {
    type: 'cleanup-collection',
    collection,
    cutoffDate: cutoffDate.toISOString(),
    batchSize: options?.batchSize || 100,
    dateField: options?.dateField || 'createdAt',
    triggeredBy: options?.triggeredBy || 'system',
  }

  const job = await queue.add('retention', data, {
    attempts: 3,
    backoff: {
      type: 'exponential',
      delay: 5000,
    },
    removeOnComplete: {
      count: 50,
      age: 7 * 24 * 60 * 60, // 7 Tage
    },
    removeOnFail: {
      count: 100,
      age: 30 * 24 * 60 * 60, // 30 Tage
    },
  })

  console.log(`[RetentionJob] Collection cleanup job ${job.id} queued for ${collection}`)
  return job
}

/**
 * Fügt einen Media-Orphan-Cleanup-Job zur Queue hinzu
 */
export async function enqueueMediaOrphanCleanup(options?: {
  batchSize?: number
  minAgeDays?: number
  triggeredBy?: string
}): Promise<Job<RetentionJobData>> {
  const queue = getQueue(QUEUE_NAMES.CLEANUP)

  // Cutoff-Datum für Mindestalter
  const cutoff = new Date()
  cutoff.setDate(cutoff.getDate() - (options?.minAgeDays || 30))

  const data: RetentionJobData = {
    type: 'cleanup-media-orphans',
    cutoffDate: cutoff.toISOString(),
    batchSize: options?.batchSize || 50,
    triggeredBy: options?.triggeredBy || 'system',
  }

  const job = await queue.add('retention', data, {
    attempts: 3,
    backoff: {
      type: 'exponential',
      delay: 5000,
    },
    removeOnComplete: {
      count: 50,
      age: 7 * 24 * 60 * 60,
    },
    removeOnFail: {
      count: 100,
      age: 30 * 24 * 60 * 60,
    },
  })

  console.log(`[RetentionJob] Media orphan cleanup job ${job.id} queued`)
  return job
}

/**
 * Fügt einen vollständigen Retention-Job zur Queue hinzu
 * (Führt alle konfigurierten Cleanups durch)
 */
export async function enqueueFullRetention(triggeredBy?: string): Promise<Job<RetentionJobData>> {
  const queue = getQueue(QUEUE_NAMES.CLEANUP)

  const data: RetentionJobData = {
    type: 'retention-full',
    triggeredBy: triggeredBy || 'scheduler',
  }

  const job = await queue.add('retention', data, {
    attempts: 1, // Full Retention sollte nicht wiederholt werden
    removeOnComplete: {
      count: 30,
      age: 30 * 24 * 60 * 60,
    },
    removeOnFail: {
      count: 50,
      age: 60 * 24 * 60 * 60,
    },
  })

  console.log(`[RetentionJob] Full retention job ${job.id} queued`)
  return job
}

/**
 * Plant wiederkehrende Retention-Jobs
 */
export async function scheduleRetentionJobs(cronExpression: string): Promise<void> {
  const queue = getQueue(QUEUE_NAMES.CLEANUP)

  // Entferne existierende Scheduler
  const repeatableJobs = await queue.getRepeatableJobs()
  for (const job of repeatableJobs) {
    if (job.name === 'scheduled-retention') {
      await queue.removeRepeatableByKey(job.key)
    }
  }

  // Neuen Scheduler hinzufügen
  await queue.add(
    'scheduled-retention',
    {
      type: 'retention-full',
      triggeredBy: 'scheduler',
    } as RetentionJobData,
    {
      repeat: {
        pattern: cronExpression,
      },
      removeOnComplete: {
        count: 30,
        age: 30 * 24 * 60 * 60,
      },
      removeOnFail: {
        count: 50,
        age: 60 * 24 * 60 * 60,
      },
    }
  )

  console.log(`[RetentionJob] Scheduled retention job with cron: ${cronExpression}`)
}

/**
 * Holt den Status eines Retention-Jobs
 */
export async function getRetentionJobStatus(jobId: string): Promise<{
  state: string
  progress: number
  result?: RetentionJobResult
  failedReason?: string
} | null> {
  const queue = getQueue(QUEUE_NAMES.CLEANUP)

  const job = await queue.getJob(jobId)
  if (!job) return null

  const [state, progress] = await Promise.all([job.getState(), job.progress])

  return {
    state,
    progress: typeof progress === 'number' ? progress : 0,
    result: job.returnvalue as RetentionJobResult | undefined,
    failedReason: job.failedReason,
  }
}
