<?php
/**
 * سودانا — Worker v2
 * Cron: * * * * * php /path/to/cron/worker.php >> /var/log/sudanna_worker.log 2>&1
 */
require_once __DIR__ . '/../config.php';
require_once __DIR__ . '/../engine/QueueEngine.php';
require_once __DIR__ . '/../engine/SupportEngines.php';
require_once __DIR__ . '/../engine/ControlEngine.php';
require_once __DIR__ . '/../engine/PolicyEngine.php';
require_once __DIR__ . '/../engine/DecisionEngine.php';
require_once __DIR__ . '/../engine/TaskEngine.php';
require_once __DIR__ . '/../engine/GrowthBrain.php';
require_once __DIR__ . '/../engine/AIOrchestrator.php';
require_once __DIR__ . '/../engine/EventBus.php';
require_once __DIR__ . '/../engine/BehaviorEngine.php';

// FILE LOCK: prevent concurrent runs
$lock = fopen(sys_get_temp_dir() . '/sudanna_worker.lock', 'c');
if (!$lock || !flock($lock, LOCK_EX | LOCK_NB)) exit(0);
register_shutdown_function(function() use ($lock) { flock($lock, LOCK_UN); fclose($lock); });

// Recover stuck tasks (worker crash recovery)
QueueEngine::recoverStuck();

// FIX 2: Recover orphan ai_agent_runs stuck in 'running' > 10 minutes
try {
    db()->exec(
        "UPDATE ai_agent_runs
         SET status = 'failed'
         WHERE status = 'running'
           AND created_at < DATE_SUB(NOW(), INTERVAL 10 MINUTE)"
    );
} catch (Throwable $e) {
    error_log('[Worker] ai_agent_runs recovery: ' . $e->getMessage());
}

// Safety gate
if (!SystemHealthMonitor::isSystemHealthy()) {
    Monitoring::log('worker.safety_blocked', 1);
    exit(0);
}

Monitoring::log('queue.depth', QueueEngine::depth());

$tasks = QueueEngine::fetch(5);
Monitoring::log('queue.fetched', count($tasks));
if (empty($tasks)) exit(0);

foreach ($tasks as $task) {
    $start = microtime(true);
    try {
        $payload = json_decode($task['payload'], true) ?? [];
        if ($task['type'] === 'event') {
            $event = $payload['event'] ?? '';
            unset($payload['event']);
            if (!$event) { QueueEngine::fail((int)$task['id'], 'missing_event_key'); continue; }
            AIOrchestrator::run($event, $payload);
        }
        QueueEngine::done((int)$task['id']);
        Monitoring::log('worker.task_latency_ms', round((microtime(true)-$start)*1000), ['type'=>$task['type']]);
        Monitoring::log('worker.task_completed', 1, ['type'=>$task['type']]);
    } catch (Throwable $e) {
        QueueEngine::fail((int)$task['id'], $e->getMessage());
        // Dead letter: if max attempts reached, log permanently
        if (($task['attempts'] ?? 0) >= 3) {
            error_log('[Worker::DEAD_LETTER] Task ' . $task['id'] . ' type=' . $task['type'] . ' msg=' . $e->getMessage());
            Monitoring::log('worker.dead_letter', 1, ['type'=>$task['type']]);
        }
        Monitoring::log('worker.task_failed', 1, ['error'=>substr($e->getMessage(),0,200)]);
        error_log("[Worker] Task {$task['id']} failed: " . $e->getMessage());
    }
    sleep(1);
}

if (rand(1,100) === 1) SelfLearningEngine::learn();

// Financial audit — runs hourly (when minute=0)
if ((int)date('i') === 0) {
    require_once __DIR__ . '/../engine/FinancialAgent.php';
    try {
        FinancialAgent::run(['source'=>'cron','timestamp'=>date('Y-m-d H:i:s')]);
        Monitoring::log('financial.audit.ran', 1);
    } catch (Throwable $e) {
        error_log('[Worker::FinancialAudit] ' . $e->getMessage());
    }
}
