<?php

declare(strict_types=1);

/**
 * Scheduled tick entry point (SPEC §17).
 *
 * Usage: php cron.php key=SECRET   (or /cron.php?key=SECRET for wget-cron)
 *
 * The internal scheduler lives in lib/Cron.php: every-run housekeeping plus
 * the board-midnight daily tick. api.php carries the pseudo-cron fallback,
 * so real cron buys promptness, never correctness.
 */

require __DIR__ . '/lib/bootstrap.php';

$isCli = PHP_SAPI === 'cli';
header_if(!$isCli, 'Content-Type: text/plain; charset=utf-8');

if (!atdt_installed()) {
    if (!$isCli) {
        http_response_code(503);
    }
    exit_msg('ATDT is not installed.', 1);
}
atdt_migrate();

// Key from argv (key=SECRET) or query string.
$key = '';
if ($isCli) {
    foreach (array_slice($GLOBALS['argv'] ?? [], 1) as $arg) {
        if (str_starts_with($arg, 'key=')) {
            $key = substr($arg, 4);
        }
    }
} else {
    $key = (string)($_GET['key'] ?? $_POST['key'] ?? '');
}

$expected = (string)(atdt_config()['cron_key'] ?? '');
if ($expected === '' || !hash_equals($expected, $key)) {
    atdt_log_event('security', $isCli ? 'cron:cli' : 'cron:' . ($_SERVER['REMOTE_ADDR'] ?? '?'), 'cron.php called with a bad key');
    if (!$isCli) {
        http_response_code(403);
    }
    exit_msg('Bad key.', 1);
}

$r = \Atdt\Cron::runDue(atdt_db(), atdt_settings());

exit_msg(sprintf(
    'OK %s reaped=%d pruned_events=%d pruned_chat=%d daily=%s',
    now_utc(),
    (int)$r['reaped'],
    (int)$r['pruned_events'],
    (int)$r['pruned_chat'],
    (string)$r['daily']
), 0);

function header_if(bool $cond, string $header): void
{
    if ($cond && !headers_sent()) {
        header($header);
    }
}

function exit_msg(string $msg, int $code): never
{
    echo $msg . "\n";
    exit($code);
}
