#!/usr/bin/env php
<?php
/**
 * =====================================================================
 *  bin/rx-migrate — bring a database up to the current schema
 *
 *  Usage:
 *    rx-migrate status       what is applied, pending or changed
 *    rx-migrate plan         what WOULD be applied, touching nothing
 *    rx-migrate up           apply everything outstanding, in order
 *
 *  Run by the installer on a fresh node, and by the auto-updater on a
 *  live one. Safe to run twice: a pack already applied is skipped.
 * =====================================================================
 */
declare(strict_types=1);

$root = dirname(__DIR__);
require $root . '/lib/migrate.php';

$cmd = $argv[1] ?? 'status';
$cfg = require $root . '/config.php';

try {
    $pdo = new PDO($cfg['dsn'], $cfg['db_user'], $cfg['db_pass'],
                   [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
} catch (PDOException $e) {
    fwrite(STDERR, "Cannot reach the database. Check that MySQL is running and that\n"
                 . "config.php has the right details.\n\n  " . $e->getMessage() . "\n");
    exit(2);
}

// MariaDB lacks MySQL 8's default collation. Detect rather than ask.
$server = (string) $pdo->query('SELECT VERSION()')->fetchColumn();
$maria  = stripos($server, 'mariadb') !== false;

$m = new Migrator($pdo, $root . '/schema', $maria);

/* A migration problem is a sentence, not a stack trace. This is read by
   a partner on a shop PC, and an uncaught exception here is the same
   failure the bootstrap preflight exists to prevent. */
try {

switch ($cmd) {
    case 'status':
        echo $m->report();
        break;

    case 'plan':
        $r = $m->migrate(true);
        if (!empty($r['already_current'])) { echo "Nothing to do.\n"; break; }
        echo "Would apply, in this order:\n";
        foreach ($r['packs'] as $i => $p) { printf("  %d. %s\n", $i + 1, $p); }
        break;

    case 'up':
        $r = $m->migrate(false, get_current_user());
        if (!empty($r['already_current'])) { echo "Already up to date.\n"; break; }
        foreach ($r['packs'] as $p) {
            printf("  applied %-34s %3d statements  %4d ms\n",
                   $p['file'], $p['statements'], $p['ms']);
        }
        printf("\n%d pack(s) applied.\n", $r['applied']);
        break;

    default:
        fwrite(STDERR, "usage: rx-migrate [status|plan|up]\n");
        exit(1);
}

} catch (MigrationException $e) {
    fwrite(STDERR, "\n" . $e->getMessage() . "\n\n");
    exit(3);
} catch (Throwable $e) {
    fwrite(STDERR, "\nThe schema update could not finish.\n\n  "
                 . $e->getMessage() . "\n\nSend this message to support.\n\n");
    exit(4);
}
