import { appendEvent } from "../modules/events/service/events-service.js"
import { issueCertificateWithCloudflareDns } from "./acme-cloudflare.js"
import {
  getIssueJobRecord,
  getServerRowByIdString,
  updateIssueJobRecord,
} from "./certificates-service.js"

const runningJobs = new Set<string>()

export async function runCertificateIssueJob(jobId: string): Promise<void> {
  if (runningJobs.has(jobId)) return
  runningJobs.add(jobId)
  const row = getIssueJobRecord(jobId)
  if (!row) {
    runningJobs.delete(jobId)
    return
  }

  const server = getServerRowByIdString(row.serverId)
  if (!server) {
    updateIssueJobRecord(jobId, {
      status: "failed",
      step: "failed",
      finishedAt: new Date().toISOString(),
      error: "Сервер не найден",
    })
    runningJobs.delete(jobId)
    return
  }

  let domainNames: string[] = []
  try {
    domainNames = JSON.parse(row.domainNames) as string[]
  } catch {
    domainNames = []
  }

  const trustStore = row.trustStore.split(",").map((s) => s.trim()).filter(Boolean)
  const startedAt = new Date().toISOString()
  const isScheduler = row.source === "scheduler"
  updateIssueJobRecord(jobId, { status: "running", step: "acme_order", startedAt, error: null })

  if (isScheduler) {
    appendEvent({
      level: "info",
      eventType: "certificates.renew.started",
      sourceModule: "certificates",
      title: "Запущено автообновление сертификата",
      message: `${row.certName} · ${domainNames.join(", ")} · ${server.name}`,
      entityType: "server",
      entityId: String(server.id),
    })
  }

  try {
    await issueCertificateWithCloudflareDns({
      server,
      certName: row.certName,
      domainNames,
      keyType: row.keyType === "ec256" ? "ec256" : "rsa2048",
      trustStore: trustStore.length > 0 ? trustStore : ["www", "api"],
      onStep: (step) => updateIssueJobRecord(jobId, { step }),
    })
    updateIssueJobRecord(jobId, {
      status: "done",
      step: "done",
      finishedAt: new Date().toISOString(),
      error: null,
    })
    appendEvent({
      level: "info",
      eventType: isScheduler ? "certificates.renew.done" : "certificates.issue.done",
      sourceModule: "certificates",
      title: isScheduler ? "Сертификат обновлён" : "Сертификат выпущен",
      message: `${row.certName} · ${domainNames.join(", ")} · ${server.name}`,
      entityType: "server",
      entityId: String(server.id),
    })
  } catch (e) {
    const message = e instanceof Error ? e.message : String(e)
    updateIssueJobRecord(jobId, {
      status: "failed",
      step: "failed",
      finishedAt: new Date().toISOString(),
      error: message,
    })
    appendEvent({
      level: "warning",
      eventType: isScheduler ? "certificates.renew.failed" : "certificates.issue.failed",
      sourceModule: "certificates",
      title: isScheduler ? "Ошибка автообновления сертификата" : "Ошибка выпуска сертификата",
      message,
      entityType: "server",
      entityId: String(server.id),
    })
  } finally {
    runningJobs.delete(jobId)
  }
}

export function queueCertificateIssueJob(jobId: string): void {
  queueMicrotask(() => { void runCertificateIssueJob(jobId) })
}
