<?php

ignore_user_abort(true);
@set_time_limit(60);

require_once __DIR__ . '/vendor/autoload.php';

use Bot\Database;
use Bot\Bot;

// Load Config
$config = require __DIR__ . '/config.php';

// Security Check
if (php_sapi_name() !== 'cli') {
    $key = $_GET['key'] ?? '';
    $secret = $_ENV['CRON_SECRET'] ?? '';
    if (empty($secret) || $key !== $secret) {
        http_response_code(403);
        die("Access Denied");
    }
    
    // Early response: close HTTP connection immediately
    while (ob_get_level()) ob_end_clean();
    ob_start();
    echo "OK";
    header('Content-Type: text/plain');
    header('Connection: close');
    header('Content-Length: ' . ob_get_length());
    ob_end_flush();
    flush();
    if (function_exists('fastcgi_finish_request')) fastcgi_finish_request();
    if (function_exists('litespeed_finish_request')) litespeed_finish_request();
}

$botDb = new Database($config['db_host'], $config['db_user'], $config['db_pass'], $config['db_name']);
$bot = new Bot($config['bot_token'], $botDb, $config['admins'], $config['owner_id']);

// Try to acquire lock to prevent concurrent execution
$lockName = 'bot_scheduled_tasks';
if (!$botDb->acquireLock($lockName, 0)) {
    // Already running
    die("Worker is busy.\n");
}

try {
    echo "[Worker] Starting scheduled tasks...\n";
    $botDb->ensureConnection();

    // 1. Process Deferred Join Requests
    $now = time();
    $deferred = $botDb->getDeferredRequests($now);
    $countDeferred = 0;

    foreach ($deferred as $req) {
        echo "Approving user {$req['user_id']} in chat {$req['chat_id']}...\n";
        $bot->approveChatJoinRequest($req['chat_id'], $req['user_id']);
        $botDb->approveJoinRequest($req['chat_id'], $req['user_id']);
        $countDeferred++;
        usleep(50000); // 50ms delay
    }
    
    // 2. Scheduled Actions (Send/Delete)
    $actions = $botDb->getPendingActions(20); // Limit 20 per run to keep it fast
    $countActions = 0;
    
    foreach ($actions as $action) {
        echo "Processing action ID: {$action['id']} Type: {$action['action_type']}\n";
        if ($action['action_type'] === 'send') {
            $msg = $botDb->getChannelMessage($action['message_template_id']);
            if ($msg) {
                 $payload = json_decode($action['payload'], true);
                 // Using public sendTemplateMessage
                 $sentMsgId = $bot->sendTemplateMessage($action['chat_id'], $msg, $payload);
                 
                 if ($sentMsgId && $msg['delete_seconds'] > 0) {
                     $botDb->scheduleDeleteAction($action['chat_id'], $sentMsgId, time() + $msg['delete_seconds']);
                 }
            }
        } elseif ($action['action_type'] === 'delete') {
             if ($action['sent_message_id']) {
                 try {
                     $bot->deleteMessage($action['chat_id'], $action['sent_message_id']);
                 } catch (\Exception $e) {
                     echo "Failed to delete message {$action['sent_message_id']}: " . $e->getMessage() . "\n";
                 }
             }
        }
        $botDb->completeAction($action['id']);
        $countActions++;
    }
    
    // 3. Cleanup Locks
    $botDb->cleanupGreetingLocks();
    
    // 4. Trigger Broadcast Worker if needed (Fail-safe)
    // Check if stalled broadcast exists
    
    $active = $botDb->getActiveBroadcast();
    $shouldTrigger = false;
    if ($active) {
         if ($active['status'] === 'pending') $shouldTrigger = true;
         elseif ($active['status'] === 'processing' && (time() - strtotime($active['locked_at'] ?? 'now') > 45)) $shouldTrigger = true;
    }
    
    if ($shouldTrigger) {
        triggerAsyncScript('process_broadcast.php');
    }
    
    echo "[Worker] Done. Processed $countDeferred requests and $countActions actions.\n";
    
    // If we processed actions, there might be more. Trigger self again?
    // Only if we hit the limit (20).
    if ($countActions >= 20) {
        echo "[Worker] More actions pending. Chaining...\n";
        triggerAsyncScript('process_tasks.php');
    }

} finally {
    // Release Lock
    $botDb->releaseLock($lockName);
}

function triggerAsyncScript($scriptName) {
    global $_ENV;
    $siteUrl = $_ENV['SITE_URL'] ?? '';
    if (!$siteUrl) return;
    
    $url = rtrim($siteUrl, '/') . '/' . $scriptName . '?key=' . urlencode($_ENV['CRON_SECRET'] ?? '');
    
    // Method 1: cURL (most compatible with shared hosting)
    if (function_exists('curl_init')) {
        $ch = curl_init();
        curl_setopt_array($ch, [
            CURLOPT_URL            => $url,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_TIMEOUT        => 2,
            CURLOPT_CONNECTTIMEOUT => 2,
            CURLOPT_NOSIGNAL       => 1,
            CURLOPT_SSL_VERIFYPEER => false,
            CURLOPT_SSL_VERIFYHOST => 0,
            CURLOPT_FOLLOWLOCATION => true,
        ]);
        @curl_exec($ch);
        curl_close($ch);
        return;
    }
    
    // Method 2: fsockopen
    $parts  = parse_url($url);
    $host   = $parts['host'] ?? 'localhost';
    $scheme = $parts['scheme'] ?? 'http';
    $port   = $parts['port'] ?? ($scheme === 'https' ? 443 : 80);
    $path   = ($parts['path'] ?? '/') . (isset($parts['query']) ? '?' . $parts['query'] : '');
    
    $fp = @fsockopen(
        ($scheme === 'https' ? 'ssl://' : '') . $host,
        $port, $errno, $errstr, 2
    );
    if ($fp) {
        fwrite($fp, "GET $path HTTP/1.1\r\nHost: $host\r\nConnection: Close\r\n\r\n");
        fclose($fp);
        return;
    }
    
    // Method 3: file_get_contents with short timeout
    $ctx = stream_context_create([
        'http' => ['timeout' => 2, 'ignore_errors' => true],
        'ssl'  => ['verify_peer' => false, 'verify_peer_name' => false]
    ]);
    @file_get_contents($url, false, $ctx);
}
