<?php
/**
 * Integration test for the in-app update / about / support fields in
 * the cPanel PHP backend. Uses an in-memory SQLite DB so it runs
 * without MySQL.
 *
 *   php /app/cpanel_build_php/test_app_info_php.php
 */

// 1) Bring constants into scope (config.php expects to define them).
define('DB_HOST', 'sqlite');
define('DB_PORT', 0);
define('DB_NAME', ':memory:');
define('DB_USER', '');
define('DB_PASS', '');
define('JWT_SECRET', 'test');
define('JWT_TTL_SECONDS', 3600);
define('ADMIN_USERNAME', 'admin');
define('ADMIN_PASSWORD', 'admin123');

// 2) Override db() to return an in-memory SQLite PDO. We declare it
//    BEFORE including the lib/db.php so that PHP picks ours.
$GLOBALS['__pdo'] = new PDO('sqlite::memory:');
$GLOBALS['__pdo']->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$GLOBALS['__pdo']->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
function db(): PDO { return $GLOBALS['__pdo']; }
function ensure_schema(): void {
    static $done = false;
    if ($done) return;
    $done = true;
    db()->exec("CREATE TABLE settings (id TEXT PRIMARY KEY, data TEXT NOT NULL)");
}

// 3) Minimal stand-ins for the bits routes/admin.php needs.
function require_admin(): void {}
function read_json_body(): array { return $GLOBALS['__body'] ?? []; }
function send_json($payload, int $code = 200): void {
    $GLOBALS['__last_response'] = $payload;
    $GLOBALS['__last_code'] = $code;
}
function uuid_v4(): string {
    return sprintf('%04x%04x', random_int(0,0xffff), random_int(0,0xffff));
}

// 4) Load the actual files under test (skip db.php — we already
//    defined db()/ensure_schema()). admin.php declares set_settings_data
//    using MySQL "ON DUPLICATE KEY UPDATE" which SQLite doesn't speak, so
//    we monkey-patch it with a portable version BEFORE the require by
//    pre-declaring it here (PHP keeps the first declaration).
function set_settings_data(array $data): void {
    unset($data['id']);
    $exists = db()->prepare('SELECT 1 FROM settings WHERE id = ?');
    $exists->execute(['global']);
    if ($exists->fetch()) {
        $up = db()->prepare('UPDATE settings SET data = ? WHERE id = ?');
        $up->execute([json_encode($data), 'global']);
    } else {
        $ins = db()->prepare('INSERT INTO settings (id, data) VALUES (?, ?)');
        $ins->execute(['global', json_encode($data)]);
    }
}
// Because admin.php redeclares set_settings_data, we strip that one
// declaration from the source before eval() — keeps the rest intact.
$src = file_get_contents(__DIR__ . '/nadiplayer/api/routes/admin.php');
$src = preg_replace(
    '/function set_settings_data\(array \$data\): void \{[^}]*\}\s*/s',
    '',
    $src,
    1
);
$src = preg_replace('/^<\?php/', '', $src, 1);
eval($src);
require __DIR__ . '/nadiplayer/api/routes/public.php';

// ──────── Test runner ────────
$failures = 0;
function assert_equals($expected, $actual, string $label): void {
    global $failures;
    if ($expected === $actual) {
        echo "  PASS  $label\n";
    } else {
        echo "  FAIL  $label\n";
        echo "        expected: " . var_export($expected, true) . "\n";
        echo "        actual:   " . var_export($actual, true) . "\n";
        $failures++;
    }
}

echo "── Test 1: GET /api/admin/settings on a fresh DB seeds defaults\n";
route_admin_get_settings();
$s = $GLOBALS['__last_response'];
assert_equals(false, $s['update_enabled'],          'default update_enabled');
assert_equals('1.0.0', $s['app_version'],           'default app_version');
assert_equals('1.0.0', $s['min_supported_version'], 'default min_supported_version');
assert_equals('',      $s['update_apk_url'],        'default update_apk_url');
assert_equals('',      $s['support_email'],         'default support_email');
assert_equals('',      $s['creator_name'],          'default creator_name');

echo "\n── Test 2: GET /api/public/app-info works without auth\n";
route_public_app_info();
$ai = $GLOBALS['__last_response'];
assert_equals(false,   $ai['update']['enabled'],          'app-info update.enabled');
assert_equals('1.0.0', $ai['update']['latest_version'],   'app-info update.latest_version');
assert_equals('+1234567890', $ai['support']['whatsapp_number'], 'app-info support.whatsapp_number');
assert_equals(true,    isset($ai['privacy_policy_text']),  'app-info privacy_policy_text key present');

echo "\n── Test 3: PUT /api/admin/settings persists ALL the new fields\n";
$GLOBALS['__body'] = [
    'update_enabled'        => true,
    'app_version'           => '1.5.0',
    'min_supported_version' => '1.2.0',
    'update_apk_url'        => 'https://example.com/update.apk',
    'update_play_url'       => 'https://play.google.com/store/apps/details?id=x',
    'update_changelog'      => "• Faster startup\n• Bug fixes",
    'whatsapp_message'      => 'Hello support!',
    'support_email'         => 'hello@nadiplayer.app',
    'creator_name'          => 'Vlog Nadi',
    'creator_role'          => 'Developer',
    'creator_avatar_url'    => 'https://example.com/me.jpg',
    'creator_bio'           => 'Hi, I built Nadiplayer.',
    'privacy_policy_text'   => 'Custom policy from admin.',
    // Pre-existing fields must still work (no regression):
    'whatsapp_number'       => '+15551234567',
    'external_player_enabled' => true,
];
route_admin_put_settings();
$saved = $GLOBALS['__last_response'];
assert_equals(true,    $saved['update_enabled'],         'saved update_enabled');
assert_equals('1.5.0', $saved['app_version'],            'saved app_version');
assert_equals('1.2.0', $saved['min_supported_version'],  'saved min_supported_version');
assert_equals('https://example.com/update.apk', $saved['update_apk_url'], 'saved update_apk_url');
assert_equals('Vlog Nadi', $saved['creator_name'],       'saved creator_name');
assert_equals('Custom policy from admin.', $saved['privacy_policy_text'], 'saved privacy_policy_text');
assert_equals('+15551234567', $saved['whatsapp_number'], 'saved whatsapp_number (regression)');
assert_equals(true,    $saved['external_player_enabled'],'saved external_player_enabled (regression)');

echo "\n── Test 4: GET /api/public/app-info reflects the saved values\n";
route_public_app_info();
$ai = $GLOBALS['__last_response'];
assert_equals(true,    $ai['update']['enabled'],          'public update.enabled');
assert_equals('1.5.0', $ai['update']['latest_version'],   'public update.latest_version');
assert_equals('1.2.0', $ai['update']['min_supported_version'], 'public min_supported_version');
assert_equals('https://example.com/update.apk', $ai['update']['apk_url'], 'public update.apk_url');
assert_equals('Vlog Nadi', $ai['creator']['name'],        'public creator.name');
assert_equals('Hello support!', $ai['support']['whatsapp_message'], 'public support.whatsapp_message');
assert_equals('hello@nadiplayer.app', $ai['support']['email'], 'public support.email');
assert_equals('Custom policy from admin.', $ai['privacy_policy_text'], 'public privacy_policy_text');

echo "\n── Test 5: Bool coercion for update_enabled\n";
$GLOBALS['__body'] = ['update_enabled' => 0];
route_admin_put_settings();
assert_equals(false, $GLOBALS['__last_response']['update_enabled'], 'update_enabled coerced from 0 to false');
$GLOBALS['__body'] = ['update_enabled' => 'yes'];
route_admin_put_settings();
assert_equals(true,  $GLOBALS['__last_response']['update_enabled'], 'update_enabled coerced from "yes" to true');

echo "\n";
if ($failures === 0) {
    echo "ALL TESTS PASSED\n";
    exit(0);
} else {
    echo "$failures test(s) FAILED\n";
    exit(1);
}
