import type { Kysely } from "kysely";

import {
  claimNextBackupJob,
  completeBackupJob,
  failBackupJob,
} from "@/application/phase9/backup-jobs";
import { requireEnvironmentVariable } from "@/infrastructure/config/load-local-env";
import { createBackupArtifact } from "@/infrastructure/backup/backup-artifact";
import type { DatabaseSchema } from "@/infrastructure/database/schema";
import { logError, logInfo } from "@/infrastructure/logging/logger";

function safeFailureCode(error: unknown): string {
  if (error instanceof Error && /^[A-Z0-9_]{3,80}$/.test(error.message)) return error.message;
  return "BACKUP_CREATION_FAILED";
}

export async function processPendingBackupJobs(
  database: Kysely<DatabaseSchema>,
  options: { readonly maximumJobs?: number } = {},
): Promise<{ readonly completed: number; readonly failed: number }> {
  const maximumJobs = options.maximumJobs ?? 10;
  const attemptedJobIds: string[] = [];
  let completed = 0;
  let failed = 0;
  for (let index = 0; index < maximumJobs; index += 1) {
    const job = await claimNextBackupJob(database, new Date(), attemptedJobIds);
    if (!job) break;
    attemptedJobIds.push(job.id);
    try {
      const result = await createBackupArtifact(requireEnvironmentVariable("DATABASE_URL"), job);
      await completeBackupJob(database, job, result);
      completed += 1;
      logInfo("backup.completed", { backupJobId: job.id, triggerType: job.triggerType });
    } catch (error) {
      const errorCode = safeFailureCode(error);
      await failBackupJob(database, job, errorCode);
      failed += 1;
      logError("backup.failed", { backupJobId: job.id, errorCode });
    }
  }
  return { completed, failed };
}
