#!/usr/bin/env php
<?php
/**
 * Führt alle aktiven Cronjobs einmal aus (z. B. manuell aus den Einstellungen).
 * Wird von api_info.php?action=run aufgerufen.
 *
 *   php /pfad/zu/wecker/cronjob_run_once.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);
}

$storageRoot = defined('STORAGE_ROOT') ? rtrim(STORAGE_ROOT, DIRECTORY_SEPARATOR) : $weckerRoot . DIRECTORY_SEPARATOR . 'storage';
$cronStateFile = $storageRoot . DIRECTORY_SEPARATOR . 'cronjob_master.json';

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) : [];
}

function cronjob_ausfuehrung_setzen(PDO $pdo, int $id): void {
    $stmt = $pdo->prepare("UPDATE cronjobs SET letzte_ausfuehrung = NOW() WHERE id = ?");
    $stmt->execute([$id]);
}

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_run_once ' . $safeName . '] ' . $e->getMessage());
        return false;
    }
}

/** State-Datei: last_activity auf jetzt setzen (für Anzeige in Einstellungen → Info). */
function cron_run_once_update_state(string $stateFile): void {
    $dir = dirname($stateFile);
    if (!is_dir($dir)) {
        @mkdir($dir, 0755, true);
    }
    $state = [
        'last_activity' => date('c'),
    ];
    if (is_file($stateFile)) {
        $content = @file_get_contents($stateFile);
        if ($content !== false && $content !== '') {
            $decoded = @json_decode($content, true);
            if (is_array($decoded)) {
                $state = array_merge($decoded, $state);
            }
        }
    }
    @file_put_contents($stateFile, json_encode($state, JSON_UNESCAPED_UNICODE));
}

try {
    $jobs = cronjobs_laden($pdo);
    foreach ($jobs as $job) {
        cronjob_ausfuehren($cronjobDir, $job['name']);
        cronjob_ausfuehrung_setzen($pdo, (int) $job['id']);
    }
    cron_run_once_update_state($cronStateFile);
    exit(0);
} catch (Throwable $e) {
    error_log('[cronjob_run_once] ' . $e->getMessage());
    exit(1);
}
