#!/usr/bin/env php
<?php
/**
 * Master-Cronjob: Läuft in Endlosschleife mit 1 Sekunde Sleep.
 * Liest aus der DB, welche Jobs aus wecker/cronjob/ in welchem Intervall laufen sollen,
 * und startet sie bei Bedarf.
 *
 * Start (im Hintergrund):
 *   php /pfad/zu/wecker/cronjob.php
 *
 * Crontab (läuft dann z.B. beim Boot):
 *   @reboot /usr/bin/php /var/www/wecker/cronjob.php
 */
$weckerRoot = __DIR__;
$config = $weckerRoot . '/config.php';
if (!is_file($config)) {
    fwrite(STDERR, "config.php nicht gefunden: " . $config . "\n");
    exit(1);
}

require $config;
require $weckerRoot . '/functions/functions_db.php';
require $weckerRoot . '/functions/functions_wecker.php';
require $weckerRoot . '/functions/functions_common.php';

$cronjobDir = $weckerRoot . '/cronjob';
if (!is_dir($cronjobDir)) {
    fwrite(STDERR, "Cronjob-Ordner nicht gefunden: " . $cronjobDir . "\n");
    exit(1);
}

$pdo = $GLOBALS['pdo'] ?? null;
if (!$pdo) {
    fwrite(STDERR, "Keine DB-Verbindung.\n");
    exit(1);
}

/** Aktivierte Cronjobs aus DB holen (Name, Intervall, letzte Ausführung) */
function cronjobs_laden(PDO $pdo): array {
    $stmt = $pdo->query("
        SELECT id, name, interval_sekunden, letzte_ausfuehrung
        FROM cronjobs
        WHERE aktiv = 1 AND interval_sekunden > 0
        ORDER BY id
    ");
    return $stmt ? $stmt->fetchAll(PDO::FETCH_ASSOC) : [];
}

/** Letzte Ausführung auf jetzt setzen */
function cronjob_ausfuehrung_setzen(PDO $pdo, int $id): void {
    $stmt = $pdo->prepare("UPDATE cronjobs SET letzte_ausfuehrung = NOW() WHERE id = ?");
    $stmt->execute([$id]);
}

/** Einzelnen Cronjob-Skript ausführen (inkl. Datei-Check) */
function cronjob_ausfuehren(string $cronjobDir, string $name): bool {
    $safeName = preg_replace('/[^a-z0-9_-]/', '', strtolower($name));
    if ($safeName === '') {
        return false;
    }
    $script = $cronjobDir . '/' . $safeName . '.php';
    if (!is_file($script)) {
        return false;
    }
    try {
        include $script;
        return true;
    } catch (Throwable $e) {
        error_log('[cronjob ' . $safeName . '] ' . $e->getMessage());
        return false;
    }
}

// Endlosschleife: jede Sekunde prüfen, welche Jobs fällig sind
while (true) {
    try {
        $jobs = cronjobs_laden($pdo);
        $now = time();
        foreach ($jobs as $job) {
            $last = $job['letzte_ausfuehrung'] ? strtotime($job['letzte_ausfuehrung']) : 0;
            $interval = max(1, (int) $job['interval_sekunden']);
            if ($now - $last >= $interval) {
                cronjob_ausfuehren($cronjobDir, $job['name']);
                cronjob_ausfuehrung_setzen($pdo, (int) $job['id']);
            }
        }
    } catch (Throwable $e) {
        error_log('[cronjob master] ' . $e->getMessage());
    }
    sleep(1);
}
