<?php
/**
 * Bichon archival test-connection API. Root-only.
 *
 *   POST ?action=test
 *     body: { url?: string, token?: string, csrf_token: string }
 *     response: { status: 'success'|'error', message: string, http_code?: int }
 *
 * If both url and token are supplied (test-before-save flow from the
 * Server Settings → Integrations tab), the BichonClient is instantiated
 * directly with the in-flight values. Otherwise we fall back to the
 * persisted, decrypted settings via BichonClient::loadConfig().
 *
 * On success we update settings.json's bichon.last_test_ok_at to the
 * current ISO 8601 UTC timestamp so the form can show "Last verified".
 *
 * SECURITY: this endpoint never logs the token or the api_token field.
 * If error_log() is added later, mask those keys explicitly.
 */

header('Content-Type: application/json');

// Auth gate — auto-prepend has already run, but defense-in-depth.
if (!defined('AUTH_USER')) {
    http_response_code(401);
    echo json_encode(['status' => 'error', 'message' => 'Authentication required']);
    exit;
}

// Root-only.
if (AUTH_USER !== 'root') {
    http_response_code(403);
    echo json_encode(['status' => 'error', 'message' => 'Forbidden']);
    exit;
}

// CSRF validation is handled globally by auto-prepend.php for authenticated
// POST requests, matching the convention of email-archival.php.

$method = $_SERVER['REQUEST_METHOD'];
$action = $_GET['action'] ?? '';

if ($method !== 'POST') {
    http_response_code(405);
    echo json_encode(['status' => 'error', 'message' => 'Method not allowed']);
    exit;
}

if ($action !== 'test') {
    http_response_code(400);
    echo json_encode(['status' => 'error', 'message' => 'Unknown action']);
    exit;
}

require_once('/docker/whp/web/libs/BichonClient.php');

try {
    $url   = isset($_POST['url'])   ? trim((string)$_POST['url'])   : '';
    $token = isset($_POST['token']) ? (string)$_POST['token']       : '';

    $client = null;

    if ($url !== '' && $token !== '') {
        // Test-before-save: use the in-flight values directly. The constructor
        // expects the token in plaintext, which is exactly what the user typed.
        if (!filter_var($url, FILTER_VALIDATE_URL)) {
            echo json_encode(['status' => 'error', 'message' => 'Bichon URL is invalid']);
            exit;
        }
        $client = new BichonClient([
            'enabled'   => true,
            'url'       => $url,
            'api_token' => $token,
        ]);
    } else {
        // Fall back to persisted (decrypted) config.
        $cfg = BichonClient::loadConfig();
        if ($cfg === null || empty($cfg['url']) || empty($cfg['api_token'])) {
            echo json_encode(['status' => 'error', 'message' => 'Bichon is not configured yet']);
            exit;
        }
        $client = new BichonClient($cfg);
    }

    $r = $client->testConnection();

    if (!empty($r['ok'])) {
        // Persist last_test_ok_at on success. Load → modify → write atomically
        // with LOCK_EX, matching the pattern used in update_bichon_settings.
        $settings_file = '/docker/whp/settings.json';
        $config = [];
        if (file_exists($settings_file)) {
            $config = json_decode(file_get_contents($settings_file), true) ?: [];
        }
        if (!isset($config['bichon']) || !is_array($config['bichon'])) {
            $config['bichon'] = [];
        }
        $config['bichon']['last_test_ok_at'] = gmdate('c');
        $payload = json_encode($config, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
        if ($payload !== false) {
            @file_put_contents($settings_file, $payload, LOCK_EX);
            @chmod($settings_file, 0600);
        }

        echo json_encode([
            'status'    => 'success',
            'message'   => 'Connected to Bichon',
            'http_code' => (int)($r['http'] ?? 0),
        ]);
        exit;
    }

    echo json_encode([
        'status'    => 'error',
        'message'   => (string)($r['msg'] ?? 'Test failed'),
        'http_code' => (int)($r['http'] ?? 0),
    ]);
    exit;

} catch (Throwable $e) {
    // Never include POST body in the error log — the token is sensitive.
    error_log('bichon-test.php: ' . $e->getMessage());
    echo json_encode(['status' => 'error', 'message' => 'Internal error']);
    exit;
}
