<?php
// ═══════════════════════════════════════════════════════════════════════════════════════════════
// PURPOSE
//   Relocates the plugin. Points SCRIPTS_DIR in varaverk.cfg at a different Varaverk checkout
//   — the manual equivalent of what the storage-migration flow does automatically.
//
// OPERATIONAL MODEL
//   varaverk.cfg is the one file whose location is fixed. Everything else the plugin reads —
//   scripts, Configurations/, Deployment/, State_Files/, data/ — is resolved relative to the
//   SCRIPTS_DIR it names, which is what makes internal-vs-appdata storage mode possible at
//   all. Rewriting that one value moves the entire plugin.
//
//   Currently unreferenced by the UI. The settings tab drives relocation through the storage
//   migration flow, which also copies the data. This endpoint changes the pointer alone, and
//   is kept as the recovery path for a cfg that points somewhere that no longer exists.
//
// DESIGN PRINCIPLES
//   Changes the pointer, never moves the data.
//       There is deliberately no copy step. Migration is a separate, longer operation with
//       its own confirmation; conflating the two would make a one-field edit capable of
//       deleting a directory.
//
//   Merges into the existing cfg rather than authoring it.
//       varaverk.cfg carries GITEA_CONTAINER, GITEA_REPO_PATH, GITEA_SSH_KEY, SSH_PORT and
//       CUSTOM_SCRIPTS_DIR alongside SCRIPTS_DIR. Only the key being changed is touched.
//
// OPERATIONAL SAFEGUARDS
//   POST only, checked before anything is read.
//
//   The target must actually be a Varaverk checkout.
//       is_dir() alone is not enough — it would happily accept /mnt/user or /tmp and leave
//       every subsequent page resolving conf and script paths under a directory that contains
//       none of them, with no single obvious symptom. common.sh and load_config.sh must both
//       be present, because those are the two files every script in the repo sources.
//
//   Unrelated keys survive the write.
//       The previous version emitted a file containing SCRIPTS_DIR and nothing else, silently
//       discarding the Gitea coordinates that git_pull_execute.sh needs — so a relocation
//       would have broken both the daily pull and the UI pull button, and only at the next
//       scheduled run. The cfg is now read, one key replaced, and all keys written back.
//
//   The write is atomic.
//       tmp + rename, so a page render or a script reading varaverk.cfg mid-save sees the old
//       file or the new one. A truncated varaverk.cfg would leave SCRIPTS_DIR undefined and
//       every path in the plugin falling back to the compiled-in default.
//
//   Values are escaped for the ini quoting parse_ini_file() expects.
//       addslashes() on every value written, not just the new one, so a path containing a
//       quote cannot terminate the string early and corrupt the keys that follow it.
//
// REQUEST
//   POST scripts_dir=<absolute path to a Varaverk checkout>
//
// RESPONSE
//   {"ok":true,"error":null}
//   {"ok":false,"error":"POST only"|"scripts_dir is required"|"Directory does not exist"
//                      |"Not a Varaverk checkout — common.sh and load_config.sh not found"
//                      |"Failed to write cfg file"}
//
// DEPENDS ON
//   include/config.php   PLUGIN_CFG
// ═══════════════════════════════════════════════════════════════════════════════════════════════
header('Content-Type: application/json');
require_once dirname(__DIR__) . '/include/config.php';

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

$scriptsDir = trim($_POST['scripts_dir'] ?? '');

if (!$scriptsDir) {
    echo json_encode(['ok' => false, 'error' => 'scripts_dir is required']);
    exit;
}

if (!is_dir($scriptsDir)) {
    echo json_encode(['ok' => false, 'error' => 'Directory does not exist']);
    exit;
}

// Pointing SCRIPTS_DIR at an arbitrary directory leaves every conf and script path in the
// plugin resolving under something that holds none of them. These two files are sourced by
// every script in the repo, so their presence is what makes a directory a checkout.
if (!file_exists($scriptsDir . '/common.sh') || !file_exists($scriptsDir . '/load_config.sh')) {
    echo json_encode([
        'ok'    => false,
        'error' => 'Not a Varaverk checkout — common.sh and load_config.sh not found',
    ]);
    exit;
}

$cfgFile = PLUGIN_CFG;
$cfgDir  = dirname($cfgFile);
if (!is_dir($cfgDir)) mkdir($cfgDir, 0755, true);

// Merge, do not author. varaverk.cfg also carries the Gitea coordinates git_pull_execute.sh
// needs — rewriting the file with SCRIPTS_DIR alone would silently break the daily pull.
$cfg = @parse_ini_file($cfgFile) ?: [];
$cfg['SCRIPTS_DIR'] = $scriptsDir;

$content = '';
foreach ($cfg as $k => $v) {
    $content .= $k . '="' . addslashes((string)$v) . '"' . "\n";
}

$tmp = $cfgFile . '.vv.tmp';
$ok  = file_put_contents($tmp, $content) !== false && rename($tmp, $cfgFile);
if (!$ok) @unlink($tmp);

echo json_encode(['ok' => $ok, 'error' => $ok ? null : 'Failed to write cfg file']);
