<?php
/**
 * planner_printnode_patch.php
 * Drop this file in /rooms/modules/payments/
 * Include it near the bottom of planner.php, before footer.php:
 *   <?php require_once __DIR__ . '/planner_printnode_patch.php'; ?>
 */

$PLANNER_PRINTNODE_PRINTERS = [
    'kitchen' => 75588290,
    'bar'     => 75588291,
    'master'  => 75588294,
    'receipt' => 75588293,
];

if (!function_exists('printnode_send_raw')) {
    require_once __DIR__ . '/printnode_print.php';
}

if (!function_exists('pn_init')) {
    function pn_init(): string { return "\x1B\x40" . "\x1B\x74\x00" . "\x1C\x2E"; }
}
if (!function_exists('pn_safe')) {
    function pn_safe(string $s): string {
        $s = str_replace(["\r\n", "\r"], "\n", $s);
        $s = iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $s) ?: $s;
        return preg_replace('/[^\x09\x0A\x0D\x20-\x7E]/', '', $s) ?? '';
    }
}
if (!function_exists('pn_esc_bold')) {
    function pn_esc_bold(bool $on): string { return $on ? "\x1B\x45\x01" : "\x1B\x45\x00"; }
}
if (!function_exists('pn_esc_align')) {
    function pn_esc_align(string $a): string { return "\x1B\x61" . (['left'=>"\x00",'center'=>"\x01",'right'=>"\x02"][$a] ?? "\x00"); }
}
if (!function_exists('pn_esc_feed')) {
    function pn_esc_feed(int $n = 3): string { return str_repeat("\x0A", max(0, $n)); }
}
if (!function_exists('pn_esc_cut')) {
    function pn_esc_cut(): string { return "\x1D\x56\x42\x00"; }
}
if (!function_exists('planner_pn_starts_with')) {
    function planner_pn_starts_with(string $haystack, string $needle): bool { return $needle === '' || strpos($haystack, $needle) === 0; }
}
if (!function_exists('pn_build_planner_ticket')) {
    function pn_build_planner_ticket(string $payload, string $jobType): string {
        $out  = pn_init();
        $lines = explode("\n", str_replace(["\r\n", "\r"], "\n", $payload));

        foreach ($lines as $line) {
            $line = pn_safe($line);
            $trimmed = trim($line);

            if (planner_pn_starts_with($trimmed, '***') || planner_pn_starts_with($trimmed, '===')) {
                $out .= pn_esc_bold(true) . pn_esc_align('center');
                $out .= $trimmed . "\n";
                $out .= pn_esc_bold(false) . pn_esc_align('left');
            } elseif (preg_match('/^[-=]{6,}$/', $trimmed)) {
                $out .= $trimmed . "\n";
            } elseif ($trimmed === '') {
                $out .= "\n";
            } elseif (preg_match('/^\s*\d[\d.]*\s+x\s+/i', $line)) {
                $out .= pn_esc_bold(true) . $line . "\n" . pn_esc_bold(false);
            } elseif (planner_pn_starts_with($trimmed, 'Note:') || planner_pn_starts_with($trimmed, '**')) {
                $out .= '  ' . $trimmed . "\n";
            } else {
                $out .= $line . "\n";
            }
        }

        $out .= pn_esc_feed(4) . pn_esc_cut();
        return $out;
    }
}

$plannerPnResults = [];
$plannerPnJobIds  = [];

$qzIdsRaw = trim((string)($_GET['qz_print_jobs'] ?? ''));
if ($qzIdsRaw !== '') {
    $plannerPnJobIds = array_values(array_filter(array_map('intval', preg_split('/[^0-9]+/', $qzIdsRaw))));
}

if (!empty($plannerPnJobIds) && function_exists('printnode_send_raw')) {
    $pnJobRows = [];
    try {
        $in = implode(',', array_fill(0, count($plannerPnJobIds), '?'));
        $pnStmt = $pdo->prepare("SELECT * FROM restaurant_print_jobs WHERE id IN ($in) ORDER BY id ASC");
        $pnStmt->execute(array_values($plannerPnJobIds));
        $pnJobRows = $pnStmt->fetchAll(PDO::FETCH_ASSOC) ?: [];
    } catch (Throwable $e) {
        $plannerPnResults[] = ['job_id'=>0, 'role'=>'system', 'type'=>'load', 'ok'=>false, 'error'=>$e->getMessage()];
    }

    foreach ($pnJobRows as $pnJob) {
        $role = strtolower(trim((string)($pnJob['printer_role'] ?? 'kitchen')));
        if ($role === '') $role = 'kitchen';
        $payload = (string)($pnJob['payload'] ?? '');
        $jobType = (string)($pnJob['job_type'] ?? 'station');
        $printerId = (int)($PLANNER_PRINTNODE_PRINTERS[$role] ?? $PLANNER_PRINTNODE_PRINTERS['kitchen'] ?? 0);

        if ($printerId <= 0 || $payload === '') continue;

        $escBytes = pn_build_planner_ticket($payload, $jobType);
        $result = printnode_send_raw($printerId, $escBytes, ucfirst($jobType) . ' - ' . ($pnJob['restaurant_order_id'] ?? ''));
        $ok = !empty($result['ok']);

        $plannerPnResults[] = [
            'job_id' => (int)$pnJob['id'],
            'role'   => $role,
            'type'   => $jobType,
            'ok'     => $ok,
            'error'  => $result['error'] ?? null,
            'pn_job' => $result['job_id'] ?? null,
        ];

        try {
            if ($ok) {
                $pdo->prepare("UPDATE restaurant_print_jobs SET status='printed', printed_at=NOW(), error_message=NULL WHERE id=:id")
                    ->execute([':id' => (int)$pnJob['id']]);
            } else {
                $pdo->prepare("UPDATE restaurant_print_jobs SET status='failed', error_message=:err WHERE id=:id")
                    ->execute([':err' => $result['error'] ?? 'PrintNode error', ':id' => (int)$pnJob['id']]);
            }
        } catch (Throwable $ignore) {}
    }
}

if (isset($_GET['test_printer']) && (int)$_GET['test_printer'] > 0 && function_exists('printnode_send_raw')) {
    $testPrinterId = (int)$_GET['test_printer'];
    try {
        $tpStmt = $pdo->prepare("SELECT * FROM restaurant_printers WHERE id=:id LIMIT 1");
        $tpStmt->execute([':id' => $testPrinterId]);
        $tp = $tpStmt->fetch(PDO::FETCH_ASSOC);
        if ($tp) {
            $role = strtolower(trim((string)($tp['printer_role'] ?? 'kitchen')));
            if ($role === '') $role = 'kitchen';
            $pnId = (int)($PLANNER_PRINTNODE_PRINTERS[$role] ?? $PLANNER_PRINTNODE_PRINTERS['kitchen'] ?? 0);

            if ($pnId > 0) {
                $testPayload =
                    "PRINTNODE TEST PRINT\n" .
                    "================================\n" .
                    "Printer: " . ($tp['printer_name'] ?? '') . "\n" .
                    "Role:    " . ($tp['printer_role'] ?? '') . "\n" .
                    "PN ID:   " . $pnId . "\n" .
                    "Date:    " . date('Y-m-d H:i:s') . "\n" .
                    "================================\n" .
                    "PrintNode connection OK\n";

                $testBytes  = pn_build_planner_ticket($testPayload, 'test');
                $testResult = printnode_send_raw($pnId, $testBytes, 'Test - ' . ($tp['printer_name'] ?? ''));

                $plannerPnResults[] = [
                    'job_id' => 0,
                    'role' => $role,
                    'type' => 'test',
                    'ok' => !empty($testResult['ok']),
                    'error' => $testResult['error'] ?? null,
                    'pn_job' => $testResult['job_id'] ?? null,
                ];
            }
        }
    } catch (Throwable $e) {
        $plannerPnResults[] = ['job_id'=>0, 'role'=>'test', 'type'=>'test', 'ok'=>false, 'error'=>$e->getMessage()];
    }
}
?>

<?php if (!empty($plannerPnResults)): ?>
<script>
(function(){
    var results = <?php echo json_encode($plannerPnResults, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); ?>;
    var ok = results.filter(function(r){ return r.ok; }).length;
    var failed = results.filter(function(r){ return !r.ok; });

    function toast(msg, type) {
        var el = document.getElementById('thermalPrintToast');
        if (!el) {
            el = document.createElement('div');
            el.id = 'thermalPrintToast';
            el.style.cssText = 'position:fixed;bottom:20px;right:20px;z-index:99999;max-width:420px;padding:10px 14px;border-radius:10px;font-size:13px;font-weight:700;box-shadow:0 8px 24px rgba(0,0,0,.22);transition:opacity .3s;opacity:0;pointer-events:none;';
            document.body.appendChild(el);
        }
        var colors = {success:['#166534','#dcfce7'], error:['#991b1b','#fee2e2'], info:['#1e3a8a','#dbeafe']};
        var c = colors[type] || colors.info;
        el.style.background = c[1];
        el.style.color = c[0];
        el.textContent = msg;
        el.style.opacity = '1';
        clearTimeout(el._t);
        el._t = setTimeout(function(){ el.style.opacity = '0'; }, 6000);
    }

    if (failed.length) {
        var errMsg = failed.map(function(r){ return (r.role || '?') + ': ' + (r.error || 'error'); }).join(', ');
        toast('PrintNode: ' + failed.length + ' ticket(s) failed — ' + errMsg, 'error');
        console.error('PrintNode print failures:', failed);
    } else if (ok > 0) {
        toast('✓ Printed ' + ok + ' ticket(s) via PrintNode', 'success');
    }
})();
</script>
<?php endif; ?>
