<?php
/** 
 * EVP - Bulk Scan Scheduler
 * Should Add It In Cron Job
 * eg: curl https://yourdomain.com/functions/tasks/scheduler.scan.php?hash=GENERATED_CODE
 **/

require_once('../../config.php');

// Ensure $log is initialized and globally accessible
global $log;
if (!isset($log)) {
    $log = new Logger(); // Replace 'Logger' with the actual class name if different
}

$log->system_debug('[START] Scan Scheduler started');

// --- RECOVERY: Reset orphaned processing emails (processing_assigned_at IS NULL) ---
$db->update("UPDATE evp_email_list SET worker_status = 'pending', processing_worker_id = NULL, processing_assigned_at = NULL WHERE worker_status = 'processing' AND processing_assigned_at IS NULL AND (email_status = 'Not Verify' OR LTRIM(RTRIM(email_status)) = '')");
$log->system_debug('[RECOVERY] Reset orphaned processing emails (processing_assigned_at IS NULL) to pending.');

// --- RECOVERY: Reset processing emails stuck for more than 15 minutes (regardless of worker) ---
$db->update("UPDATE evp_email_list SET worker_status = 'pending', processing_worker_id = NULL, processing_assigned_at = NULL WHERE worker_status = 'processing' AND (email_status = 'Not Verify' OR LTRIM(RTRIM(email_status)) = '') AND processing_assigned_at < NOW() - INTERVAL 10 MINUTE");
$log->system_debug('[RECOVERY] Reset stuck processing emails (processing_assigned_at older than 15 min) to pending.');

// Recover stuck emails: processing but not updated for 15 minutes
$db->update("UPDATE evp_email_list 
    SET worker_status = 'pending', processing_worker_id = NULL 
    WHERE worker_status = 'processing' 
    AND last_update < NOW() - INTERVAL 10 MINUTE");

// First clear any stale locks (locks older than 15 minutes)
$db->update("UPDATE evp_task 
             SET meta = JSON_REMOVE(meta, '$.import_locked', '$.import_pid', '$.import_locked_until') 
             WHERE JSON_EXTRACT(meta, '$.import_locked_until') < NOW() - INTERVAL 15 MINUTE 
             AND JSON_EXTRACT(meta, '$.import_locked') = true");

// Check if any import task is available for processing (not locked)
$import_task_check = $db->select("
    SELECT id FROM evp_task
    WHERE status = 'importing' 
      AND (JSON_EXTRACT(meta, '$.import_locked') IS NULL 
          OR JSON_EXTRACT(meta, '$.import_locked') = false 
          OR JSON_EXTRACT(meta, '$.import_locked_until') < NOW())
    LIMIT 1
");
if ($import_task_check && $import_task_check->num_rows > 0) {
    $log->system_debug('[INFO] Found available import task, starting import process');
    include_once('scheduler.import.php');
} else {
    $log->system_debug('[INFO] No import tasks available for scheduler.import.php to process.');
}

if (isset($_GET['hash']) && ($_GET['hash'] == $apiKey_scanner)) {
    $log->system_debug('[INFO] Hash matched, starting scan task loop');

    global $csv_pq_read, $csv_pq_check, $csv_pq_data, $check_mailbox, $task_user_id, $task_status, $last_exec, $task_csv_name, $host, $task_exit_data, $total_verify, $filename, $total_email, $scan_status;

    $csv_pq = "SELECT e_mdata.*, e_task.status, e_task.last_exec
    FROM evp_email_list_metadata e_mdata
    LEFT JOIN evp_task e_task
    ON e_mdata.csv_file_name = e_task.csv_name
    WHERE e_mdata.scan_status = 'processing'";
    $csv_pq_read = $db->select($csv_pq);
    $csv_pq_check = mysqli_num_rows($csv_pq_read);
    if ($csv_pq_check > 0):
        $log->system_debug('[INFO] Found ' . $csv_pq_check . ' processing scan tasks');

        // Send Email On Completed
        $rows = array();
        while ($row = $csv_pq_read->fetch_assoc()) {
            $rows[] = $row;
        }

        foreach ($rows as $row) {
            $filename = $row['csv_file_name'];
            $user_id = $row['user_id'];
            $scan_status = $row['scan_status'];
            $pid = $row['pid'];
            $task_status = $row['status'];
            $last_exec = strtotime($row['last_exec']);
            $check_mailbox = $row['check_mailbox'];
            $count_valid = $row['valid'];
            $count_invalid = $row['invalid'];
            $count_catchall = $row['catch_all'];
            $count_unknown = $row['unknown'];
            $count_skipped = $row['skipped'];
            $count_syntax_error = $row['syntax_error'];
            $count_disposable = $row['disposable'];
            $count_free_account = $row['free_account'];
            $count_role_account = $row['role_account'];
            $scan_time = $row['scan_time'];
            $scan_status = $row['scan_status'];
            $total_verify = $count_valid + $count_invalid + $count_catchall + $count_unknown + $count_skipped;
            $total_email = $row['total'];
            $user_id = $row['user_id'];
            $count_not_verify = $total_email - $total_verify;

            $new_time = strtotime("-1 minutes");
            $log->system_debug("[TASK] $filename | total: $total_email | verified: $total_verify | user: $user_id");
            if (($total_verify == $total_email) && ($scan_status == 'processing') && ($task_status != 'email_check')) {
                $log->system_debug("[COMPLETE] All emails verified for $filename. Marking complete.");
                $sendmail = new SendMail;
                if ($check_mailbox == 'true') {
                    $sendmail->verify_mailbox($check_mailbox);
                }
                $sendmail->scan_done();
                $log->system_debug('[INFO] Cleared PID in database for: ' . $filename);

                // Clear the PID in the database after scan completion
                $db->update("UPDATE evp_email_list_metadata SET pid = NULL WHERE csv_file_name = '$filename'");
                continue;
            }

            $reboot = false;
            if (!function_exists('is_process_running')) {
                function is_process_running($pid)
                {
                    global $log; // Ensure $log is accessible inside the function
                    $log->system_debug('Checking if process is running: ' . $pid);
                    return file_exists("/proc/$pid");
                }
            }

            // --- PID check and reboot logic ---
            $reboot = false;
            if (!empty($pid)) {
                $log->system_debug('[INFO] PID exists in database: ' . $pid . ' for ' . $filename);
                if (!file_exists("/proc/$pid")) {
                    $log->system_debug('[WARN] PID ' . $pid . ' not running for ' . $filename . '. Clearing PID and rebooting scan.');
                    $db->update("UPDATE evp_email_list_metadata SET pid = NULL WHERE csv_file_name = '$filename' AND user_id = '$user_id'");
                    $reboot = true;
                } else {
                    $log->system_debug('[INFO] v_email.php process is already running for ' . $filename . '.');
                    continue;
                }
            } else {
                $log->system_debug('[INFO] No PID exists in database for ' . $filename . '. Creating and starting process...');
                $reboot = true;
            }

            // --- Assign pseudo-PID before starting/rebooting scan process ---
            if ($reboot) {
                $pseudo_pid = time() . rand(1000, 9999);
                $db->update("UPDATE evp_email_list_metadata SET pid = '$pseudo_pid' WHERE csv_file_name = '$filename' AND user_id = '$user_id'");
                $log->system_debug('[INFO] Assigned pseudo-PID ' . $pseudo_pid . ' for ' . $filename);
                // Start v_email.php process for this filename
                $task_start = curl_init();
                curl_setopt($task_start, CURLOPT_URL, "$s_url/functions/email_verify.php");
                curl_setopt($task_start, CURLOPT_POST, true);
                curl_setopt($task_start, CURLOPT_POSTFIELDS, [
                    'filename' => $filename,
                    'uid' => $user_id,
                    'total_workers' => $total_workers
                ]);
                curl_setopt($task_start, CURLOPT_TIMEOUT, 30);
                curl_setopt($task_start, CURLOPT_HEADER, 0);
                curl_setopt($task_start, CURLOPT_SSL_VERIFYHOST, false);
                curl_setopt($task_start, CURLOPT_SSL_VERIFYPEER, false);
                curl_setopt($task_start, CURLOPT_RETURNTRANSFER, false);
                curl_setopt($task_start, CURLOPT_FORBID_REUSE, true);
                curl_setopt($task_start, CURLOPT_CONNECTTIMEOUT, 30);
                curl_setopt($task_start, CURLOPT_FRESH_CONNECT, true);
                curl_setopt($task_start, CURLOPT_VERBOSE, 0);
                curl_exec($task_start);

            } elseif (($scan_status == 'processing') && ($check_mailbox == 'true') && ($total_verify == $total_email) && ($task_status != 'email_check')) {
                $log->system_debug('[INFO] Email Check Task -> Recall for ' . $filename);
                $task_status = 'email_check';
                $task_start = curl_init();
                curl_setopt($task_start, CURLOPT_URL, "$s_url/functions/email_verify.php?filename=$filename&uid=$user_id&inbox_check=$task_status");
                curl_setopt($task_start, CURLOPT_TIMEOUT, 1);
                curl_setopt($task_start, CURLOPT_HEADER, 0);
                curl_setopt($task_start, CURLOPT_SSL_VERIFYHOST, false);
                curl_setopt($task_start, CURLOPT_SSL_VERIFYPEER, false);
                curl_setopt($task_start, CURLOPT_RETURNTRANSFER, false);
                curl_setopt($task_start, CURLOPT_FORBID_REUSE, true);
                curl_setopt($task_start, CURLOPT_CONNECTTIMEOUT, 1);
                curl_setopt($task_start, CURLOPT_FRESH_CONNECT, true);
                curl_setopt($task_start, CURLOPT_VERBOSE, 0);
                curl_exec($task_start);

            } elseif (($scan_status == 'completed') && ($total_verify == $total_email) && ($task_status != 'hold')) {
                $log->system_debug('[CLEANUP] Task deleted as completed for ' . $filename);
                $task_delete_current = "DELETE FROM evp_task WHERE csv_name = '$filename' AND user_id = '$user_id' AND status != 'hold'";
                $db->select($task_delete_current);
            } else {
                $log->system_debug('[INFO] No action required for ' . $filename);
            }

            if ($new_time > $last_exec) {
                // $log->system_debug('New Time: ' . $new_time);
            } else {
                // $log->system_debug('Old Time: ' . $last_exec);
            }
        }

    else:
        $log->system_debug('[INFO] No processing scan tasks found. Nothing to do.');

    endif;
} else {
    $log->system_debug('[ERROR] Invalid or missing hash. Redirecting to login.');
    header("location: ../members/login.php");
    exit();
}