#!/usr/bin/env node
import os from "node:os"
import { FedeoApi } from "./api.js"
import { loadConfig } from "./config.js"
import { log } from "./logger.js"
import { listPrinters } from "./print/cups.js"
import { hasSane, listScanners, runScan } from "./scan/sane.js"

const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms))

const stringifyError = (error: unknown) => {
    if (error instanceof Error) return error.message
    return String(error)
}

const main = async () => {
    const config = loadConfig()
    const api = new FedeoApi(config)

    log.info("FEDEO Geräte-Agent startet", {
        platform: process.platform,
        workDir: config.workDir,
        pollSeconds: config.pollSeconds,
    })

    while (true) {
        try {
            const scannerNames = await listScanners()
            const printerNames = await listPrinters()
            const scanAvailable = await hasSane()

            const heartbeat = await api.heartbeat({
                capabilities: {
                    scan: scanAvailable,
                    print: printerNames.length > 0,
                    platform: process.platform,
                },
                scannerNames,
                printerNames,
                debugInfo: {
                    hostname: os.hostname(),
                    release: os.release(),
                    arch: os.arch(),
                    node: process.version,
                    uptimeSeconds: Math.round(os.uptime()),
                },
            })

            if (heartbeat.pendingScanJobs > 0) {
                log.info(`${heartbeat.pendingScanJobs} Scan-Auftrag/Aufträge warten`)
            }

            const next = await api.nextScanJob()
            if (!next.job) {
                await sleep(config.pollSeconds * 1000)
                continue
            }

            log.info("Scan-Auftrag wird ausgeführt", {
                jobId: next.job.id,
                tenantId: next.job.tenantId,
                scannerName: next.job.scannerName || config.scannerName || "default",
            })

            try {
                await api.updateScanJobStatus(next.job.id, "running")
                const scanResult = await runScan(config, next.job)
                await api.uploadScan(next.job.id, scanResult)

                log.info("Scan-Auftrag abgeschlossen", {
                    jobId: next.job.id,
                    file: scanResult.filename,
                })
            } catch (error) {
                const message = stringifyError(error)
                log.error("Scan-Auftrag fehlgeschlagen", {
                    jobId: next.job.id,
                    message,
                })

                await api.updateScanJobStatus(next.job.id, "failed", message)
            }
        } catch (error) {
            log.error("Agent-Schleife fehlgeschlagen", stringifyError(error))
            await sleep(config.pollSeconds * 1000)
        }
    }
}

main().catch((error) => {
    log.error("Agent konnte nicht gestartet werden", stringifyError(error))
    process.exit(1)
})
