<?php
/**
 * send_push.php
 * Helper function to send "Show enabled" web-push notifications from the webserver.
 *
 * Function: try_send_show_notification(string $job, string $jobdir, string $mvlog_root = null, string $logfile = null): bool
 *
 * Returns true on successful send and cache update, false otherwise.
 */

function try_send_show_notification($job, $jobdir, $mvlog_root = null, $logfile = null)
{
    if ($mvlog_root === null) $mvlog_root = dirname(__DIR__);
    if ($logfile === null) $logfile = '/var/log/mvlog_notify.log';

    $subs_file = $mvlog_root . '/cache/push_subscriptions.json';
    $cache_file = $mvlog_root . '/cache/push_notifications.json';
    $push_config_candidates = [
        $mvlog_root . '/push.json',
        (getenv('HOME') !== false ? getenv('HOME') . '/.config/mvlog/push.json' : null),
        '/etc/mvlog/push.json',
    ];

    // Don't notify for hidden jobs
    if (is_file($jobdir . '/.mvlog-hidden')) {
        error_log("[mvlog] job $job hidden, skipping push\n", 3, $logfile);
        return false;
    }

    // Gather subscriptions
    if (!is_file($subs_file)) {
        error_log("[mvlog] subscriptions file missing, skipping push for $job\n", 3, $logfile);
        return false;
    }
    $subs_raw = @file_get_contents($subs_file);
    if (!is_string($subs_raw) || trim($subs_raw) === '') {
        error_log("[mvlog] subscriptions empty, skipping push for $job\n", 3, $logfile);
        return false;
    }
    $subs = json_decode($subs_raw, true);
    if (!is_array($subs) || count($subs) === 0) {
        error_log("[mvlog] subscriptions invalid/empty, skipping push for $job\n", 3, $logfile);
        return false;
    }

    // Read cache and check if already shown
    $cache = [];
    if (is_file($cache_file)) {
        $cache = json_decode((string)@file_get_contents($cache_file), true) ?: [];
    }
    $shown = isset($cache['shown']) && is_array($cache['shown']) ? $cache['shown'] : [];
    if (isset($shown[$job])) {
        error_log("[mvlog] push already sent for $job, skipping\n", 3, $logfile);
        return false;
    }

    // Determine push config file
    $push_config = null;
    foreach ($push_config_candidates as $candidate) {
        if (!$candidate) continue;
        if (is_file($candidate) && is_readable($candidate)) { $push_config = $candidate; break; }
    }
    if (!$push_config) {
        error_log("[mvlog] push config not found, skipping push for $job\n", 3, $logfile);
        return false;
    }

    // Determine a title/url for the notification. Prefer existing output filename if present.
    $title = preg_replace('/_+/', ' ', $job);
    $title = ucwords($title);
    $state_file = $jobdir . '/.movmaker-state.json';
    if (is_file($state_file)) {
        $state = json_decode(@file_get_contents($state_file), true) ?: [];
        if (!empty($state['output']) && is_string($state['output'])) {
            $out = pathinfo($state['output'], PATHINFO_FILENAME);
            if ($out) {
                $title = preg_replace('/_+/', ' ', $out);
                $title = ucwords($title);
            }
        }
    }

    $payload = json_encode([
        'title' => 'Show enabled',
        'body' => $title,
        'url'  => "https://bubulescu.org/mvlog/?job={$job}",
        'tag'  => "mvlog-show-{$job}",
    ], JSON_UNESCAPED_UNICODE);

    // Call node send_push.js with subscriptions on stdin
    $send_script = escapeshellarg($mvlog_root . '/send_push.js');
    $push_config_esc = escapeshellarg($push_config);
    $payload_esc = escapeshellarg($payload);
    $cmd = "node $send_script $push_config_esc $payload_esc";

    $descriptorspec = [
        0 => ['pipe', 'r'], // stdin
        1 => ['pipe', 'w'], // stdout
        2 => ['pipe', 'w'], // stderr
    ];

    $proc = proc_open($cmd, $descriptorspec, $pipes);
    if (!is_resource($proc)) {
        error_log("[mvlog] failed to start node send_push process for $job\n", 3, $logfile);
        return false;
    }

    // Write subscriptions to stdin
    fwrite($pipes[0], $subs_raw);
    fclose($pipes[0]);

    $stdout = stream_get_contents($pipes[1]); fclose($pipes[1]);
    $stderr = stream_get_contents($pipes[2]); fclose($pipes[2]);

    $rc = proc_close($proc);
    if ($rc !== 0) {
        error_log("[mvlog] send_push failed for $job rc=$rc stdout=" . trim($stdout) . " stderr=" . trim($stderr) . "\n", 3, $logfile);
        return false;
    }

    // On success, record in cache['shown']
    if (!is_array($cache)) $cache = [];
    if (!isset($cache['shown']) || !is_array($cache['shown'])) $cache['shown'] = [];
    $cache['shown'][$job] = ['sent_at' => date(DATE_ATOM)];

    // Atomic write: write to tmp then rename
    $tmp = $cache_file . '.tmp.' . bin2hex(random_bytes(6));
    $json = json_encode($cache, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) . "\n";
    if (@file_put_contents($tmp, $json, LOCK_EX) === false) {
        error_log("[mvlog] failed to write cache temp file for $job\n", 3, $logfile);
        return false;
    }
    @chmod($tmp, 0664);
    if (!@rename($tmp, $cache_file)) {
        @unlink($tmp);
        error_log("[mvlog] failed to atomically write cache file for $job\n", 3, $logfile);
        return false;
    }

    error_log("[mvlog] show-notification sent: $job\n", 3, $logfile);
    return true;
}
