import { appendEvent } from "../modules/events/service/events-service.js"
import type { BackupsRunSnapshot } from "../types/scheduler-run-snapshot.js"
import { SCHEDULER_RUN_SNAPSHOT_VERSION } from "../types/scheduler-run-snapshot.js"
import {
  getBackupScheduleSettings,
  isBackupDue,
  pruneBackupsForServer,
  resolveBackupServerIds,
  runBackupForServer,
  touchBackupScheduleRunMeta,
} from "./backup-service.js"

let collecting = false

export function getBackupSchedulerCollectorState(): { running: boolean } {
  return { running: collecting }
}

export async function collectScheduledBackupsOnce(): Promise<BackupsRunSnapshot> {
  const sampledAt = new Date().toISOString()
  const settings = getBackupScheduleSettings()
  const snapshot: BackupsRunSnapshot = {
    v: SCHEDULER_RUN_SNAPSHOT_VERSION,
    job: "backups",
    sampledAt,
    due: false,
    created: 0,
    failures: 0,
    pruned: 0,
    errors: [],
  }

  if (collecting) {
    snapshot.skipped = true
    return snapshot
  }

  if (!settings.enabled) {
    snapshot.skipped = true
    return snapshot
  }

  const due = isBackupDue(new Date(), settings, settings.lastRunAt)
  snapshot.due = due
  if (!due) {
    return snapshot
  }

  if (settings.format !== "rsc") {
    snapshot.skipped = true
    snapshot.errors = ["Формат backup пока не поддерживается, используйте rsc"]
    touchBackupScheduleRunMeta({
      lastRunAt: sampledAt,
      lastDurationMs: 0,
      lastError: snapshot.errors[0],
    })
    return snapshot
  }

  collecting = true
  const started = Date.now()
  const serverIds = resolveBackupServerIds(settings)

  appendEvent({
    level: "info",
    eventType: "backups.job.started",
    sourceModule: "backups",
    title: "Запущен плановый бэкап",
    message: `Серверов в очереди: ${serverIds.length}`,
    entityType: "backup_job",
    entityId: "scheduler",
    payload: { serverIds, scheduled: true },
  })

  try {
    for (const id of serverIds) {
      try {
        await runBackupForServer(id, "auto")
        snapshot.created += 1
      } catch (e) {
        const message = e instanceof Error ? e.message : String(e)
        snapshot.failures += 1
        snapshot.errors?.push(`${id}: ${message}`)
      }
    }

    for (const id of serverIds) {
      snapshot.pruned += await pruneBackupsForServer(id, settings.keepCount)
    }

    touchBackupScheduleRunMeta({
      lastRunAt: sampledAt,
      lastDurationMs: Date.now() - started,
      lastError: snapshot.errors?.length ? snapshot.errors.join("; ") : null,
    })

    appendEvent({
      level: snapshot.failures > 0 ? "warning" : "info",
      eventType: "backups.job.done",
      sourceModule: "backups",
      title: snapshot.failures > 0 ? "Плановый бэкап завершен с ошибками" : "Плановый бэкап завершен",
      message: `Создано: ${snapshot.created}, ошибок: ${snapshot.failures}`,
      entityType: "backup_job",
      entityId: "scheduler",
      payload: {
        total: serverIds.length,
        completed: snapshot.created + snapshot.failures,
        failures: snapshot.errors,
        pruned: snapshot.pruned,
      },
    })

    return snapshot
  } catch (e) {
    const message = e instanceof Error ? e.message : String(e)
    snapshot.fatalError = message
    snapshot.errors?.push(message)
    touchBackupScheduleRunMeta({
      lastRunAt: sampledAt,
      lastDurationMs: Date.now() - started,
      lastError: message,
    })
    appendEvent({
      level: "critical",
      eventType: "backups.job.failed",
      sourceModule: "backups",
      title: "Плановый бэкап прерван",
      message,
      entityType: "backup_job",
      entityId: "scheduler",
    })
    return snapshot
  } finally {
    collecting = false
  }
}
