#!/usr/bin/env php
<?php
/**
 * 文章任务 CLI Runner — 供宝塔 Shell 脚本类型计划任务调用
 * 用法: php /www/wwwroot/{站点目录}/admin/cli/article-task-runner-cli.php
 */

if (php_sapi_name() !== 'cli') {
    echo "此脚本仅限 CLI 模式运行。\n";
    exit(1);
}

// 模拟必要的 $_SERVER 变量以满足 bootstrap 需求
$_SERVER['REQUEST_METHOD'] = 'CLI';
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
$_SERVER['HTTP_HOST'] = 'localhost';
$_SERVER['REQUEST_URI'] = '/admin/cli/article-task-runner-cli.php';
if (!isset($_SERVER['SERVER_NAME'])) {
    $_SERVER['SERVER_NAME'] = 'localhost';
}

// 确保创建的目录/文件对 www 用户可写（避免 root 运行时权限问题）
umask(0002);

require __DIR__ . '/../../app/bootstrap.php';
require __DIR__ . '/../../app/database.php';

// CLI 模式不需要 token 验证（仅服务器本地执行）
session_write_close();
ignore_user_abort(true);
@set_time_limit(0);

$limit = 3;
foreach ($argv as $i => $arg) {
    if ($i === 0) continue;
    if (preg_match('/^--limit=(\d+)$/', $arg, $m)) {
        $limit = (int)$m[1];
    }
}

$runtimeDir = __DIR__ . '/../../runtime';
if (!is_dir($runtimeDir)) {
    @mkdir($runtimeDir, 0755, true);
}
$logFile = $runtimeDir . '/article-task-runner.log';
$lockFile = $runtimeDir . '/article-task-runner.lock';

function runner_log($msg) {
    global $logFile;
    $line = '[' . date('Y-m-d H:i:s') . '] ' . $msg . "\n";
    @file_put_contents($logFile, $line, FILE_APPEND | LOCK_EX);
    echo $line;
}

// 文件锁防并发
$lockFp = @fopen($lockFile, 'c');
if ($lockFp && !flock($lockFp, LOCK_EX | LOCK_NB)) {
    runner_log('--- CLI Runner skipped (another instance is running).');
    fclose($lockFp);
    exit(0);
}

runner_log('--- CLI Runner called.');
runner_log('  SAPI=' . PHP_SAPI . ' is_cli=' . (is_cli_request() ? 'Y' : 'N'));
$_diagLic = license_config();
runner_log('  license_config: code=' . (!empty($_diagLic['activation_code']) ? substr($_diagLic['activation_code'], 0, 6) . '...' : 'EMPTY') . ' status=' . (isset($_diagLic['status']) ? $_diagLic['status'] : 'N/A') . ' end_date=' . (isset($_diagLic['end_date']) ? $_diagLic['end_date'] : 'N/A'));
runner_log('  license_is_expired=' . (license_is_expired() ? 'Y' : 'N') . ' license_is_activated=' . (license_is_activated() ? 'Y' : 'N'));

try {
    $pdo = db_connection();
    $allTaskRows = $pdo->query("SELECT id, task_name, status, next_run_at, last_run_at, interval_seconds FROM article_generation_tasks ORDER BY id DESC LIMIT 5")->fetchAll(PDO::FETCH_ASSOC);
    foreach ($allTaskRows as $tr) {
        runner_log('  Task #' . $tr['id'] . ' [' . $tr['task_name'] . '] status=' . $tr['status'] . ' next_run=' . ($tr['next_run_at'] ?: 'NULL') . ' last_run=' . ($tr['last_run_at'] ?: 'NULL') . ' interval=' . $tr['interval_seconds']);
    }
    runner_log('  Server now=' . date('Y-m-d H:i:s') . ' limit=' . $limit);

    $dueTasks = list_due_article_generation_tasks($limit);
    runner_log('  Due tasks found: ' . count($dueTasks));
    foreach ($dueTasks as $dt) {
        runner_log('    Due: #' . ($dt['id'] ?? 0) . ' [' . ($dt['task_name'] ?? '') . '] status=' . ($dt['status'] ?? '') . ' next_run=' . ($dt['next_run_at'] ?? 'NULL'));
    }

    if (count($dueTasks) > 0) {
        $results = run_due_article_generation_tasks($limit);
        runner_log('  Executed: ' . count($results) . ' tasks');
        foreach ($results as $r) {
            $success = isset($r['success']) ? ($r['success'] ? 'Y' : 'N') : '?';
            $msg = isset($r['message']) ? $r['message'] : (isset($r['data']['message']) ? $r['data']['message'] : '');
            runner_log('    Result: task#' . ($r['task_id'] ?? 0) . ' success=' . $success . ' msg=' . $msg);
        }
    } else {
        runner_log('  No due tasks, nothing to execute.');
    }
} catch (Exception $e) {
    runner_log('  ERROR: ' . $e->getMessage());
    exit(1);
}

// 释放锁
if ($lockFp) {
    flock($lockFp, LOCK_UN);
    fclose($lockFp);
}
runner_log('--- CLI Runner finished.');
