<?php
declare(strict_types=1);

$LOG_FILE = '/home/enrepco/pdfQueueWorker.log';
$CORE_GEN = '/home/enrepco/enrepcore.enrep.co.uk/functions/generators/genPDF2.php';

function rr_log(string $msg): void {
   /// global $LOG_FILE;
    ///@file_put_contents($LOG_FILE, '[' . date('Y-m-d H:i:s') . '] ' . $msg . "\n", FILE_APPEND);
}

set_exception_handler(function (Throwable $e) {
    rr_log('EXCEPTION: ' . $e->getMessage() . ' in ' . $e->getFile() . ':' . $e->getLine());
    rr_log($e->getTraceAsString());
    exit(1);
});

register_shutdown_function(function () {
    $err = error_get_last();
    if ($err && in_array($err['type'], [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR], true)) {
        rr_log('FATAL: ' . $err['message'] . ' in ' . $err['file'] . ':' . $err['line']);
    }
});

function rr_admin_connect(): mysqli {
    $admin_host = "localhost";
    $admin_db_user = "enrepco_stmadmacc";
    $admin_db_password = "gCV^Aj@ky}19";
    $admin_db_name = "enrepco_sysmanager";

    $db = mysqli_connect($admin_host, $admin_db_user, $admin_db_password, $admin_db_name);
    if (!$db) {
        rr_log('Admin DB connect failed: ' . mysqli_connect_error());
        exit(1);
    }
    mysqli_set_charset($db, 'utf8mb4');
    return $db;
}

function rr_claim(mysqli $db, int $id, int $lockUntil): bool {
    $t = time();
    $st = $db->prepare("UPDATE `pdf_queue` SET `status`='processing', `started_at`=?, `locked_until`=? WHERE `id`=? AND `status`='pending'");
    if (!$st) return false;
    $st->bind_param('iii', $t, $lockUntil, $id);
    $st->execute();
    $ok = ($st->affected_rows === 1);
    $st->close();
    return $ok;
}

function rr_mark_done(mysqli $db, int $id): void {
    $st = $db->prepare("DELETE FROM `pdf_queue` WHERE `id`=?");
    if (!$st) return;
    $st->bind_param('i', $id);
    $st->execute();
    $st->close();
}


function rr_mark_fail(mysqli $db, int $id, string $err): void {
    $t = time();
    $err = mb_substr($err, 0, 8000);
    $st = $db->prepare("UPDATE `pdf_queue` SET `status`='failed', `attempts`=`attempts`+1, `last_error`=?, `finished_at`=?, `locked_until`=0 WHERE `id`=?");
    if (!$st) return;
    $st->bind_param('sii', $err, $t, $id);
    $st->execute();
    $st->close();
}

function rr_mkdir(string $path): bool {
    if (is_dir($path)) return true;
    return @mkdir($path, 0755, true);
}


/* ========= JOB MODE ========= */
$argv = $_SERVER['argv'] ?? [];
$argc = $_SERVER['argc'] ?? 0;

if ($argc >= 2 && $argv[1] === '--job') {

    $tenantRaw = (string)($argv[2] ?? '');
    $tenantRaw = trim($tenantRaw);

    $tenantTrim = trim($tenantRaw, "/ \t\n\r\0\x0B");
    $tenantReq  = '/' . $tenantTrim;

    $clientnumber = intval($argv[3] ?? 0);
    $itemnumber = intval($argv[4] ?? 0);
    $repnumber = intval($argv[5] ?? 0);
    $imageMode = intval($argv[6] ?? 0) === 1 ? '1' : '0';
    $tagMode = intval($argv[7] ?? 0) === 1 ? '1' : '0';

    if ($tenantTrim === '' || $clientnumber <= 0 || $itemnumber <= 0 || $repnumber <= 0) {
        rr_log("JOB fail: bad args tenantRaw={$tenantRaw} tenantTrim={$tenantTrim} client={$clientnumber} item={$itemnumber} rep={$repnumber}");
        echo "2";
        exit(2);
    }

    $cfg = "/home/enrepco/{$tenantTrim}/config.php";
    if (!file_exists($cfg)) {
        rr_log("JOB fail: tenant config missing: {$cfg}");
        echo "3";
        exit(3);
    }
    if (!file_exists($CORE_GEN)) {
        rr_log("JOB fail: core generator missing: {$CORE_GEN}");
        echo "6";
        exit(6);
    }

    require $cfg;

    if ($imageMode === '1') {
        $reportImagePattern = "/home/enrepco/{$tenantTrim}/images/report_images/{$itemnumber}_*.jpg";
        $reportImages = glob($reportImagePattern);
        $hasReportImage = false;
        if (is_array($reportImages)) {
            foreach ($reportImages as $reportImage) {
                if (strpos((string)$reportImage, 'thumb') === false) {
                    $hasReportImage = true;
                    break;
                }
            }
        }
        if (!$hasReportImage) $imageMode = '0';
    }

    $_REQUEST['tenant'] = $tenantReq;

    $_REQUEST['clientnumber'] = (string)$clientnumber;
    $_GET['clientnumber'] = (string)$clientnumber;

    $_REQUEST['repnumber'] = (string)$repnumber;
    $_GET['repnumber'] = (string)$repnumber;

    $_REQUEST['items'] = (string)$itemnumber;
    $_GET['items'] = (string)$itemnumber;

    $_REQUEST['imageMode'] = $imageMode;
    $_GET['imageMode'] = $imageMode;
    $_REQUEST['imageset'] = $imageMode;
    $_GET['imageset'] = $imageMode;

    $_REQUEST['tagMode'] = $tagMode;
    $_GET['tagMode'] = $tagMode;
    $_REQUEST['tagmode'] = $tagMode;
    $_GET['tagmode'] = $tagMode;

    $oldCwd = @getcwd();
    $genDir = dirname($CORE_GEN);
    @chdir($genDir);

    ob_start();
    include $CORE_GEN;
$out = ob_get_clean();

if ($oldCwd) @chdir($oldCwd);

// expected PDF path (matches template filestore)
$tenantTrimSafe = trim((string)$tenantTrim, "/ \t\n\r\0\x0B");
$tenantBase = '/home/enrepco/' . $tenantTrimSafe;

$expected = $tenantBase . '/output/reports/' . $clientnumber . '/' . $repnumber . '_' . $itemnumber . '.pdf';
$pdfOk = (is_file($expected) && filesize($expected) > 500);

// If no PDF was created, then treat warnings/errors as failure
if (!$pdfOk) {
    $low = strtolower((string)$out);
    if (trim((string)$out) !== '' && (strpos($low, 'fatal error') !== false || strpos($low, 'uncaught') !== false || strpos($low, 'warning') !== false)) {
        rr_log("JOB fail: generator output error tenant={$tenantReq} rep={$repnumber} item={$itemnumber}");
        rr_log(mb_substr((string)$out, 0, 4000));
        echo "5";
        exit(5);
    }

    rr_log("JOB fail: PDF not found expected={$expected} tenant={$tenantReq} rep={$repnumber} item={$itemnumber}");
    if (trim((string)$out) !== '') rr_log(mb_substr((string)$out, 0, 2000));
    echo "7";
    exit(7);
}

// PDF exists: success, but log warnings for cleanup
if (is_string($out) && trim($out) !== '') {
    $low = strtolower($out);
    if (strpos($low, 'warning') !== false || strpos($low, 'notice') !== false || strpos($low, 'deprecated') !== false) {
        rr_log("JOB warnings (PDF OK) tenant={$tenantReq} rep={$repnumber} item={$itemnumber}");
        rr_log(mb_substr((string)$out, 0, 2000));
    }
}


rr_log("JOB ok: tenant={$tenantReq} rep={$repnumber} item={$itemnumber} client={$clientnumber}");
echo "0";
exit(0);
}

/* ========= WORKER MODE ========= */
rr_log('Worker start');

$admin_con = rr_admin_connect();

$limit = 50;
$now = time();
$lockFor = 300;

$stmt = $admin_con->prepare("
    SELECT `id`,`tenant`,`clientnumber`,`itemnumber`,`repnumber`
    FROM `pdf_queue`
    WHERE `status`='pending'
      AND `locked_until` <= ?
      AND `attempts` < 5
    ORDER BY `id` ASC
    LIMIT {$limit}
");
if (!$stmt) {
    rr_log('Prepare failed: ' . $admin_con->error);
    echo "0\n";
    exit;
}
$stmt->bind_param('i', $now);
$stmt->execute();
$rs = $stmt->get_result();
$stmt->close();

if (!$rs || $rs->num_rows === 0) {
    rr_log('No pending jobs');
    echo "0\n";
    exit;
}

$processed = 0;

while ($job = $rs->fetch_assoc()) {
    $id = intval($job['id']);
    $tenant = (string)$job['tenant'];
    $clientnumber = intval($job['clientnumber']);
    $itemnumber = intval($job['itemnumber']);
    $repnumber = intval($job['repnumber']);
    $imageMode = 0;
    $tagMode = 0;

    if (!rr_claim($admin_con, $id, $now + $lockFor)) continue;

    $cmd = escapeshellcmd(PHP_BINARY) . ' -q ' . escapeshellarg(__FILE__)
        . ' --job '
        . escapeshellarg($tenant) . ' '
        . escapeshellarg((string)$clientnumber) . ' '
        . escapeshellarg((string)$itemnumber) . ' '
        . escapeshellarg((string)$repnumber) . ' '
        . escapeshellarg((string)$imageMode) . ' '
        . escapeshellarg((string)$tagMode);

    $output = [];
    $ret = 0;
    exec($cmd . ' 2>&1', $output, $ret);
    $outText = trim(implode("\n", $output));

    if ($ret === 0) {
        rr_mark_done($admin_con, $id);
        $processed++;
    } else {
        $msg = $outText !== '' ? $outText : ('Job failed rc=' . $ret);
        rr_mark_fail($admin_con, $id, $msg);
        rr_log("Queue fail id={$id} tenant={$tenant} rep={$repnumber} item={$itemnumber} rc={$ret}");
        if ($outText !== '') rr_log(mb_substr($outText, 0, 2000));
    }
}

rr_log('Worker end processed=' . $processed);
echo (string)$processed;
