<?php
// ═══════════════════════════════════════════════════════════════════════════════════════════════
// PURPOSE
//   Rsync tier toggle. Flips one *_RSYNC_ENABLED boolean in master.conf and propagates the
//   changed file to every partner host — the enable switches on the rsync tab.
//
// OPERATIONAL MODEL
//   master.conf is shared, not per-host. A tier flag has to mean the same thing on both sides
//   of the partnership or a sync will run from one end and not the other, so the write is
//   always followed by a push. The push is a no-op on a non-owner: vv_push_master_conf()
//   returns empty when this host has no SSH key, so a partner flipping a flag locally does
//   not overwrite the owner's file.
//
//   Two flags exist at different levels — RSYNC_ENABLED is the global gate and the tier flags
//   (CRITICAL_, INTERMEDIATE_, DAILY_, WEEKLY_, FALLBACK_) sit under it. This endpoint treats
//   them identically; the precedence lives in the shell layer.
//
// DESIGN PRINCIPLES
//   Toggles existing flags, never creates them.
//       vv_conf_flag_set() rewrites a line that already matches NAME=true|false and returns
//       false when nothing matched. A typo'd flag name fails loudly rather than appending a
//       key no script reads.
//
//   Push results are reported, not swallowed.
//       The per-host push outcome is returned in the response so the page can show that a
//       partner did not receive the change. A flag that is set on one host and not the other
//       is exactly the state that produces a one-sided sync.
//
//   Setup state is pushed alongside the conf.
//       vv_push_setup_state() runs after the conf push so the partner's onboarding view
//       reflects the same reality — the two are written together because they are read
//       together.
//
// OPERATIONAL SAFEGUARDS
//   POST only, checked before any parameter is read.
//
//   The flag name is constrained to the rsync namespace.
//       ^[A-Z_]+_RSYNC_ENABLED$ — this endpoint cannot be used to flip an unrelated boolean
//       in master.conf. Every other conf edit goes through confform.php or config.php, which
//       have their own rules; a general-purpose flag setter would bypass all of them.
//
//   Anything other than the literal "1" is treated as false.
//       ($_POST['enabled'] ?? '0') === '1' — strict comparison against one value, so a
//       missing, malformed, or unexpected parameter disables rather than enables. Failing
//       toward off is the safe direction for a flag that starts data movement.
//
//   The conf write is atomic.
//       vv_conf_flag_set() writes through vv_write_conf_raw() (tmp + rename). Every script
//       sources master.conf, so a truncated write would be a system-wide outage.
//
//   The push only happens after a confirmed local write.
//       Guarded on $ok, so a failed edit cannot distribute a stale or partly-written conf to
//       partners.
//
//   Related risk, not guarded here: turning RSYNC_ENABLED on for HOST2 onboarding requires
//   re-reading the --merge-run / --delete interlock in Rsync/rsync.sh first. That is a
//   property of the sync, not of this switch, and this endpoint does not enforce it.
//
// REQUEST
//   POST name=<TIER>_RSYNC_ENABLED  enabled=0|1
//
// RESPONSE
//   {"ok":true,"error":null,"push":[{"host","ok","ready","error"}, …]}
//   {"ok":false,"error":"POST only"|"Invalid flag name"|"Failed to write master.conf",
//    "push":[]}
//
// DEPENDS ON
//   include/scheduler.php   vv_conf_flag_set() → vv_write_conf_raw()
//   include/config.php      vv_push_master_conf(), vv_push_setup_state()
// ═══════════════════════════════════════════════════════════════════════════════════════════════
header('Content-Type: application/json');
require_once dirname(__DIR__) . '/include/scheduler.php';

if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    echo json_encode(['ok' => false, 'error' => 'POST only']);
    exit;
}

$name    = trim($_POST['name']    ?? '');
$enabled = ($_POST['enabled'] ?? '0') === '1';

if (!$name || !preg_match('/^[A-Z_]+_RSYNC_ENABLED$/', $name)) {
    echo json_encode(['ok' => false, 'error' => 'Invalid flag name']);
    exit;
}

$ok = vv_conf_flag_set($name, $enabled);

// master.conf is shared — propagate the change to partner hosts (no-op on non-owner).
$push = [];
if ($ok) {
    $push = vv_push_master_conf();
    vv_push_setup_state();
}

echo json_encode(['ok' => $ok, 'error' => $ok ? null : 'Failed to write master.conf', 'push' => $push]);
