#!/usr/bin/env php
<?php
/**
 * Re-encrypt the SMTP password after rotating APP_KEY.
 *
 * Usage:
 *   php scripts/reencrypt-smtp-password.php <new_base64_key> [DB_PATH]
 *
 * Steps performed:
 *   1. Read old APP_KEY from the .env file adjacent to this script's app root.
 *   2. Decrypt the current password from smtp_settings using the old key.
 *   3. Encrypt it with the new key.
 *   4. Write the new ciphertext back to the DB.
 *   5. Update app/.env with the new APP_KEY.
 *
 * After running this script, redeploy or manually update app/.env on every
 * environment that shares the same database.
 */

$newKeyB64 = $argv[1] ?? '';
$dbPath    = $argv[2] ?? null;

if ($newKeyB64 === '') {
    fwrite(STDERR, "Usage: php reencrypt-smtp-password.php <new_base64_key> [DB_PATH]\n");
    fwrite(STDERR, "Generate a key: php -r \"echo base64_encode(random_bytes(32));\"\n");
    exit(1);
}

$newKeyRaw = base64_decode($newKeyB64, strict: true);
if ($newKeyRaw === false || strlen($newKeyRaw) !== 32) {
    fwrite(STDERR, "ERROR: new key must be a base64-encoded 32-byte value.\n");
    exit(1);
}

// Locate app root (script lives in app/scripts/ or scripts/ next to app/)
$candidates = [
    __DIR__ . '/../app',   // repo root / scripts/
    __DIR__ . '/..',       // app / scripts/
];
$appRoot = null;
foreach ($candidates as $c) {
    if (file_exists(realpath($c) . '/src/Crypto.php')) {
        $appRoot = realpath($c);
        break;
    }
}
if ($appRoot === null) {
    fwrite(STDERR, "ERROR: could not locate app root (looking for src/Crypto.php).\n");
    exit(1);
}

define('APP_ROOT', $appRoot);
require_once $appRoot . '/src/Crypto.php';

$dbPath = $dbPath ?? $appRoot . '/storage/xamxam.db';
if (!file_exists($dbPath)) {
    fwrite(STDERR, "ERROR: database not found: $dbPath\n");
    exit(1);
}

$pdo = new PDO('sqlite:' . $dbPath);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

$row = $pdo->query("SELECT password FROM smtp_settings WHERE id = 1")->fetch(PDO::FETCH_ASSOC);
if (!$row) {
    fwrite(STDERR, "ERROR: no smtp_settings row found.\n");
    exit(1);
}

// Decrypt with the old key (read from existing .env via Crypto::decrypt)
$plaintext = Crypto::decrypt($row['password']);
if ($plaintext === '') {
    echo "Password is empty — nothing to re-encrypt.\n";
    exit(0);
}

// Encrypt with the new key directly (bypass the singleton so we can supply a different key)
$iv  = random_bytes(12);
$tag = '';
$cipher = openssl_encrypt($plaintext, 'aes-256-gcm', $newKeyRaw, OPENSSL_RAW_DATA, $iv, $tag, '', 16);
if ($cipher === false) {
    fwrite(STDERR, "ERROR: encryption failed: " . openssl_error_string() . "\n");
    exit(1);
}
$newBlob = base64_encode($iv . $tag . $cipher);

// Write new ciphertext to DB
$pdo->prepare("UPDATE smtp_settings SET password = ? WHERE id = 1")->execute([$newBlob]);
echo "DB updated with new ciphertext.\n";

// Update .env
$envFile = $appRoot . '/.env';
$envContent = file_exists($envFile) ? file_get_contents($envFile) : '';
if (preg_match('/^APP_KEY=.*/m', $envContent)) {
    $envContent = preg_replace('/^APP_KEY=.*/m', 'APP_KEY=' . $newKeyB64, $envContent);
} else {
    $envContent .= "APP_KEY={$newKeyB64}\n";
}
file_put_contents($envFile, $envContent);
echo ".env updated with new APP_KEY.\n";
echo "Done. Redeploy app/.env to all environments: just deploy-env\n";
