<?php
/**
 * Telegram bot one-file installer for cPanel/shared hosting.
 * Upload package, extract, open /install.php, fill the form, then delete this file.
 */
declare(strict_types=1);

error_reporting(E_ALL);
ini_set('display_errors', '1');
header('Content-Type: text/html; charset=utf-8');

$root = __DIR__;
$lockFile = $root . '/install.lock';
$force = isset($_GET['force']) && $_GET['force'] === '1';

function h($v): string { return htmlspecialchars((string)$v, ENT_QUOTES, 'UTF-8'); }
function is_post(): bool { return strtoupper($_SERVER['REQUEST_METHOD'] ?? 'GET') === 'POST'; }
function installer_bool($v): bool { return in_array(strtolower((string)$v), ['1','true','yes','on'], true); }
function installer_base_url(): string {
    $https = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off');
    $scheme = $https ? 'https' : 'http';
    $host = $_SERVER['HTTP_HOST'] ?? '';
    $dir = rtrim(str_replace('\\', '/', dirname($_SERVER['SCRIPT_NAME'] ?? '')), '/');
    if ($dir === '/') $dir = '';
    return $host ? $scheme . '://' . $host . $dir : '';
}
function write_php_file(string $path, string $content): bool {
    $tmp = $path . '.tmp';
    if (@file_put_contents($tmp, $content, LOCK_EX) === false) return false;
    return @rename($tmp, $path);
}
function php_export_string(string $value): string { return var_export($value, true); }
function ensure_dir(string $path): void { if (!is_dir($path)) @mkdir($path, 0775, true); }
function json_write_if_missing(string $path, $data): void {
    if (!is_file($path)) @file_put_contents($path, json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT), LOCK_EX);
}
function json_force_write(string $path, $data): void {
    @file_put_contents($path, json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT), LOCK_EX);
}
function cleanup_sample_config_files(string $root): array {
    $done = [];
    foreach (['config.sample.php', 'config_db.sample.php'] as $sample) {
        $path = $root . '/' . $sample;
        if (!is_file($path)) continue;
        if (@unlink($path)) {
            $done[] = $sample;
            continue;
        }
        $backup = $root . '/' . $sample . '.installed.bak';
        if (@rename($path, $backup)) {
            $done[] = $sample . ' -> ' . basename($backup);
        }
    }
    return $done;
}
function run_schema(PDO $pdo, string $schemaFile): array {
    if (!is_file($schemaFile)) return ['ok'=>false, 'error'=>'sql/schema.sql پیدا نشد.'];
    $sql = trim((string)file_get_contents($schemaFile));
    if ($sql === '') return ['ok'=>true, 'count'=>0];
    $statements = [];
    $buffer = '';
    $inString = false;
    $quote = '';
    $len = strlen($sql);
    for ($i = 0; $i < $len; $i++) {
        $ch = $sql[$i];
        $prev = $i > 0 ? $sql[$i - 1] : '';
        if (($ch === "'" || $ch === '"') && $prev !== '\\') {
            if (!$inString) { $inString = true; $quote = $ch; }
            elseif ($quote === $ch) { $inString = false; $quote = ''; }
        }
        if ($ch === ';' && !$inString) {
            $stmt = trim($buffer);
            if ($stmt !== '') $statements[] = $stmt;
            $buffer = '';
        } else {
            $buffer .= $ch;
        }
    }
    $tail = trim($buffer);
    if ($tail !== '') $statements[] = $tail;

    $count = 0;
    foreach ($statements as $stmt) {
        if ($stmt === '') continue;
        $pdo->exec($stmt);
        $count++;
    }
    return ['ok'=>true, 'count'=>$count];
}
function set_telegram_webhook(string $token, string $webhookUrl): array {
    if (!function_exists('curl_init')) return ['ok'=>false, 'error'=>'cURL روی هاست فعال نیست.'];
    $ch = curl_init();
    curl_setopt_array($ch, [
        CURLOPT_URL => 'https://api.telegram.org/bot' . $token . '/setWebhook',
        CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => ['url' => $webhookUrl],
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_CONNECTTIMEOUT => 10,
        CURLOPT_TIMEOUT => 25,
        CURLOPT_SSL_VERIFYPEER => true,
        CURLOPT_SSL_VERIFYHOST => 2,
    ]);
    $raw = curl_exec($ch);
    $err = curl_error($ch);
    $errno = curl_errno($ch);
    $http = (int)curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);
    $decoded = json_decode((string)$raw, true);
    return [
        'ok' => $raw !== false && is_array($decoded) && !empty($decoded['ok']),
        'http_code' => $http,
        'curl_errno' => $errno,
        'curl_error' => $err,
        'response' => $decoded ?: $raw,
    ];
}
function install_runtime_defaults(string $root, string $admin): void {
    $dirs = [
        'cache', 'cache/runtime', 'melat', 'ads', 'photos', 'lib/spam', 'lib/kodam', 'app/lib/kodam',
        'lib/keyboard', 'lib/keyboard/home', 'lib/Button', 'lib/others', 'lib/others/codes'
    ];
    foreach ($dirs as $d) ensure_dir($root . '/' . $d);

    json_force_write($root . '/cache/broadcast_queue.json', ['jobs'=>[]]);
    json_write_if_missing($root . '/melat.json', ['members'=>0]);
    json_write_if_missing($root . '/shop-factor.json', ['factor'=>[]]);
    json_write_if_missing($root . '/app/melat.json', ['members'=>0]);
    json_write_if_missing($root . '/app/shop-factor.json', ['factor'=>[]]);
    json_force_write($root . '/lib/kodam/list.json', ['admins'=>[(string)$admin], 'ban'=>[]]);

    $defaults = [
        'data-ads.json' => ['Lock-sabtads'=>'❌غیر فعال','sabtads'=>'دستی','eteleatch'=>'❌غیر فعال','noeeads'=>'متنی'],
        'data-Cancellads.json' => ['Condition'=>'✅فعال','mincancell'=>'1','timecancell'=>'10','Coefficientadscoin'=>'0.5'],
        'data-left.json' => ['enabled'=>'✅فعال','leftday'=>'3','ksrleft'=>'2','afzleft'=>'1','max_checks'=>'20','grace_minutes'=>'30','confirm_attempts'=>'2','notify_user'=>'✅فعال','notify_owner'=>'✅فعال','auto_penalty'=>'✅فعال'],
        'data-admin-tools.json' => ['maintenance_enabled'=>'❌غیر فعال','maintenance_text'=>'🛠 ربات موقتاً در حال بروزرسانی است. لطفاً کمی بعد دوباره تلاش کنید.','backup_enabled'=>'✅فعال','backup_keep'=>7,'last_backup_ts'=>0,'backup_password_hash'=>''],
        'data-advanced-tools.json' => ['tickets_enabled'=>'✅فعال','notices_enabled'=>'✅فعال','fraud_new_user_limit_enabled'=>'✅فعال','new_user_first_hours'=>24,'new_user_order_limit'=>5,'default_level'=>'normal','snapshot_keep'=>3,'cleanup_days'=>90],
        'data-violation.json' => ['enabled'=>'✅فعال','threshold'=>10,'admin_direct_delete'=>'✅فعال','notify_admin'=>'✅فعال'],
        'data-antispam.json' => ['enabled'=>'✅فعال','max_messages'=>5,'window_seconds'=>10,'block_minutes'=>3],
        'data-daily.json' => ['enabled'=>'✅فعال','amount'=>3,'interval_days'=>1,'channel_button_enabled'=>'✅فعال','notify_enabled'=>'❌غیر فعال','notify_text'=>'🎁 **الماس روزانه شما آماده دریافت است**
هدیه امروز شما AMOUNT MONEY است.','success_text'=>'✅ گرفتی!
AMOUNT MONEY به حسابت اضافه شد.
موجودی فعلی: BALANCE MONEY
دریافت بعدی بعد از DAYS روزه.','cooldown_text'=>'⏱ هدیه این دوره را قبلاً گرفتی.
زمان باقی‌مانده: REMAINING'],
        'data-power.json' => ['power'=>'روشن','power-text'=>'✅فعال','powertext'=>'ربات فعال است'],
        'data-transfer.json' => ['Condition'=>'❌غیر فعال','Report'=>'❌غیر فعال','mintrnfr'=>'10','maxtrnfr'=>'100'],
        'data-zirmjmae.json' => ['power-join'=>'✅فعال','banerzir'=>'🖼عکس دار','power'=>'✅فعال','Report'=>'✅فعال','zirjoinads'=>'20','coin-join'=>'10','signup_reward_mode'=>'diamond','active_reward_mode'=>'diamond','invitecoin1'=>'10','invitecoin2'=>'15','invitecoin3'=>'20','ref_join_reward_power'=>'✅فعال','ref_join_reward_per_channel'=>'10','upgrade_professional_refs'=>'10','upgrade_vip_refs'=>'20','notify_referrer_on_pending'=>'✅فعال','notify_referrer_on_verified'=>'✅فعال','anti_fake_enabled'=>'✅فعال','require_forced_join_for_reward'=>'✅فعال'],
        'channel_map.json' => [],
        'channel_reward_users.json' => [],
        'reward_cooldown.json' => [],
        'self_reward.json' => [],
    ];
    foreach ($defaults as $file => $data) {
        json_write_if_missing($root . '/lib/kodam/' . $file, $data);
        json_write_if_missing($root . '/app/lib/kodam/' . $file, $data);
    }
    foreach (['channel.txt','channel2.txt','cht.txt','giftch.txt'] as $file) {
        foreach (['lib/kodam','app/lib/kodam'] as $dir) {
            $path = $root . '/' . $dir . '/' . $file;
            if (!is_file($path)) @file_put_contents($path, '', LOCK_EX);
        }
    }

    foreach (glob($root . '/cache/*.lock') ?: [] as $file) @unlink($file);
    foreach (glob($root . '/cache/*fatal*.log') ?: [] as $file) @unlink($file);
    foreach (glob($root . '/cache/runtime/*') ?: [] as $file) @is_file($file) && @unlink($file);
}

function installer_seed_button_defaults(string $root, ?PDO $pdo = null): int {
    $defaultsFile = $root . '/lib/button_defaults.php';
    if (!is_file($defaultsFile)) return 0;
    include_once $defaultsFile;
    if (!function_exists('bot_button_default_values')) return 0;
    $count = 0;
    foreach (bot_button_default_values() as $rel => $value) {
        $path = $root . '/' . str_replace('\\', '/', (string)$rel);
        $dir = dirname($path);
        if ($dir && !is_dir($dir)) @mkdir($dir, 0775, true);
        // Fresh installer: write all core button names and keyboard slots explicitly.
        @file_put_contents($path, (string)$value, LOCK_EX);
        $count++;
        if ($pdo instanceof PDO && (strpos($rel, 'lib/Button/') === 0 || strpos($rel, 'lib/keyboard/') === 0 || strpos($rel, 'lib/kodam/') === 0)) {
            try {
                $type = (substr((string)$rel, -5) === '.json') ? 'json' : 'text';
                $st = $pdo->prepare('INSERT INTO bot_settings (setting_key, storage_type, storage_value) VALUES (?,?,?) ON DUPLICATE KEY UPDATE storage_type=VALUES(storage_type), storage_value=VALUES(storage_value), updated_at=CURRENT_TIMESTAMP');
                $st->execute([(string)$rel, $type, (string)$value]);
            } catch (Throwable $e) {
                // File seeding is still enough for non-SQL/fallback mode; keep installer running.
            }
        }
    }
    return $count;
}


function installer_self_test(string $root, ?PDO $pdo, string $baseUrl, string $token, string $admin): array {
    $checks = [];
    $add = function($name, $ok, $detail = '') use (&$checks) {
        $checks[] = ['name'=>$name, 'ok'=>(bool)$ok, 'detail'=>(string)$detail];
    };
    $add('PHP 8.0+', version_compare(PHP_VERSION, '8.0.0', '>='), PHP_VERSION);
    $add('cURL فعال', function_exists('curl_init'), function_exists('curl_init') ? 'ok' : 'missing');
    $add('PDO MySQL فعال', class_exists('PDO') && in_array('mysql', PDO::getAvailableDrivers(), true), '');
    $add('SSL/HTTPS آدرس ربات', stripos($baseUrl, 'https://') === 0, $baseUrl);
    foreach (['cache','lib','lib/kodam','lib/Button','lib/keyboard/home'] as $dir) {
        $path = $root . '/' . $dir;
        $add('نوشتن در ' . $dir, is_dir($path) && is_writable($path), '');
    }
    $add('config.php ساخته شد', is_file($root . '/config.php'), '');
    $add('config_db.php ساخته شد', is_file($root . '/config_db.php'), '');
    $add('bot.php موجود است', is_file($root . '/bot.php'), '');
    $add('cron_all_telegram.php موجود است', is_file($root . '/cron_all_telegram.php'), '');
    $button = is_file($root . '/lib/Button/dok1.txt') ? trim((string)file_get_contents($root . '/lib/Button/dok1.txt')) : '';
    $add('دکمه اصلی جمع‌آوری الماس', $button === '💎 جمع اوری الماس', $button);
    if ($pdo instanceof PDO) {
        $tables = ['bot_users','bot_orders','bot_settings','bot_admin_logs','bot_wallet_ledger','bot_support_tickets','bot_user_levels','bot_notices','bot_order_status_log'];
        foreach ($tables as $table) {
            try { $pdo->query('SELECT 1 FROM ' . $table . ' LIMIT 1'); $ok = true; $detail = 'ok'; }
            catch (Throwable $e) { $ok = false; $detail = $e->getMessage(); }
            $add('جدول ' . $table, $ok, $detail);
        }
        try {
            $st = $pdo->prepare('INSERT INTO bot_install_checks (check_key,status,message,data_json) VALUES (?,?,?,?)');
            $bad = array_values(array_filter($checks, fn($c) => empty($c['ok'])));
            $st->execute(['installer_self_test', $bad ? 'warning' : 'ok', 'install.php final self test', json_encode($checks, JSON_UNESCAPED_UNICODE)]);
        } catch (Throwable $e) {}
    }
    return $checks;
}
function installer_self_test_html(array $checks): string {
    $bad = 0; $html = '<ul>';
    foreach ($checks as $c) {
        if (empty($c['ok'])) $bad++;
        $html .= '<li>' . (empty($c['ok']) ? '❌ ' : '✅ ') . h($c['name']) . ($c['detail'] !== '' ? ' — <code>' . h($c['detail']) . '</code>' : '') . '</li>';
    }
    $html .= '</ul>';
    $html .= $bad ? '<b>نتیجه تست نصب: ' . $bad . ' مورد نیاز به بررسی دارد.</b>' : '<b>نتیجه تست نصب: همه تست‌های اصلی پاس شد.</b>';
    return $html;
}

$errors = [];
$results = [];
$defaultBase = installer_base_url();

if (is_file($lockFile) && !$force) {
    echo '<!doctype html><html lang="fa" dir="rtl"><meta charset="utf-8"><title>نصب انجام شده</title><body style="font-family:tahoma;max-width:850px;margin:40px auto;line-height:1.9">';
    echo '<h2>نصب قبلاً انجام شده است.</h2>';
    echo '<p>برای امنیت، فایل <code>install.php</code> را از هاست حذف کن. اگر واقعاً می‌خواهی دوباره نصب کنی، آدرس را با <code>?force=1</code> باز کن.</p>';
    echo '</body></html>';
    exit;
}

$values = [
    'api_key' => '',
    'admin_id' => '',
    'bot_username' => '',
    'base_url' => $defaultBase,
    'zarinpal_merchant' => '',
    'zarinpal_currency' => 'IRR',
    'zarinpal_sandbox' => '0',
    'sql_enabled' => '1',
    'db_host' => 'localhost',
    'db_name' => '',
    'db_user' => '',
    'db_pass' => '',
    'db_charset' => 'utf8mb4',
    'set_webhook' => '1',
    'cron_secret' => '',
    'backup_password' => '',
    'backup_password_confirm' => '',
];

if (is_post()) {
    foreach ($values as $k => $v) $values[$k] = isset($_POST[$k]) ? trim((string)$_POST[$k]) : $v;
    $values['zarinpal_sandbox'] = isset($_POST['zarinpal_sandbox']) ? '1' : '0';
    $values['sql_enabled'] = isset($_POST['sql_enabled']) ? '1' : '0';
    $values['set_webhook'] = isset($_POST['set_webhook']) ? '1' : '0';

    $token = preg_replace('/\s+/', '', $values['api_key']);
    $admin = preg_replace('/\s+/', '', $values['admin_id']);
    $botUsername = ltrim($values['bot_username'], '@');
    $baseUrl = rtrim($values['base_url'], '/');

    if (!preg_match('/^\d+:[A-Za-z0-9_\-]+$/', $token)) $errors[] = 'توکن ربات تلگرام معتبر نیست.';
    if ($admin === '' || !preg_match('/^\d+$/', $admin)) $errors[] = 'آیدی عددی ادمین باید عددی باشد.';
    if ($baseUrl === '' || !filter_var($baseUrl, FILTER_VALIDATE_URL) || stripos($baseUrl, 'https://') !== 0) $errors[] = 'آدرس عمومی ربات باید با https شروع شود.';
    if ($botUsername !== '' && !preg_match('/^[A-Za-z0-9_\.]+$/u', $botUsername)) $errors[] = 'یوزرنیم ربات معتبر نیست.';
    if (strlen($values['backup_password']) < 4) $errors[] = 'رمز بکاپ باید حداقل ۴ کاراکتر باشد.';
    if ($values['backup_password'] !== $values['backup_password_confirm']) $errors[] = 'تکرار رمز بکاپ با رمز اصلی یکی نیست.';

    $sqlEnabled = $values['sql_enabled'] === '1';
    $pdo = null;
    if ($sqlEnabled) {
        foreach (['db_host'=>'هاست دیتابیس','db_name'=>'نام دیتابیس','db_user'=>'یوزر دیتابیس'] as $key=>$label) {
            if ($values[$key] === '') $errors[] = $label . ' خالی است.';
        }
        if (!$errors) {
            try {
                $dsn = 'mysql:host=' . $values['db_host'] . ';dbname=' . $values['db_name'] . ';charset=' . ($values['db_charset'] ?: 'utf8mb4');
                $pdo = new PDO($dsn, $values['db_user'], $values['db_pass'], [
                    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
                    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
                    PDO::ATTR_EMULATE_PREPARES => false,
                ]);
                $results[] = 'اتصال دیتابیس موفق بود.';
            } catch (Throwable $e) {
                $errors[] = 'اتصال دیتابیس ناموفق بود: ' . $e->getMessage();
            }
        }
    }

    if (!$errors) {
        $webPanelHash = password_hash($values['backup_password'], PASSWORD_DEFAULT);
        $config = "<?php\n";
        $config .= "error_reporting(0);\n\n";
        $config .= "define('API_KEY', " . php_export_string($token) . ");\n\n";
        $config .= "$" . "admin = " . php_export_string($admin) . ";\n";
        $config .= "// ادمین‌های اصلی؛ برای اضافه‌کردن ادمین اصلی دیگر، آیدی عددی را به این آرایه اضافه کن.\n";
        $config .= "$" . "main_admins = [" . php_export_string($admin) . "];\n";
        $config .= "$" . "boter_id = " . php_export_string($botUsername) . ";\n";
        $config .= "$" . "botsaz_id = " . php_export_string($admin) . ";\n";
        $config .= "$" . "id_adady = " . php_export_string($admin) . ";\n";
        $config .= "$" . "tokens_bot = API_KEY;\n\n";
        $config .= "define('ZARINPAL_MERCHANT_ID', " . php_export_string($values['zarinpal_merchant']) . ");\n";
        $config .= "define('ZARINPAL_CURRENCY', " . php_export_string($values['zarinpal_currency'] ?: 'IRR') . ");\n";
        $config .= "define('ZARINPAL_SANDBOX', " . ($values['zarinpal_sandbox'] === '1' ? 'true' : 'false') . ");\n";
        $config .= "define('BOT_PUBLIC_BASE_URL', " . php_export_string($baseUrl) . ");\n";
        $config .= "define('BOT_BROADCAST_PER_RUN', 20);\n";
        $config .= "define('BOT_BROADCAST_MAX_PER_RUN', 20);\n";
        $config .= "define('BOT_TELEGRAM_BROADCAST_SAFE_RPS', 20);\n";
        $config .= "define('WEB_ADMIN_PASSWORD_HASH', " . php_export_string($webPanelHash) . ");\n";
        $config .= "define('BACKUP_DOWNLOAD_PASSWORD_HASH', " . php_export_string($webPanelHash) . ");\n";
        $config .= "define('ZARINPAL_CALLBACK_URL', BOT_PUBLIC_BASE_URL . '/zarinpal_callback.php');\n";
        if ($values['cron_secret'] !== '') $config .= "define('CRON_SECRET', " . php_export_string($values['cron_secret']) . ");\n";
        $config .= "?>\n";

        $dbConfig = "<?php\n";
        $dbConfig .= "define('BOT_SQL_ENABLED', " . ($sqlEnabled ? 'true' : 'false') . ");\n";
        $dbConfig .= "define('BOT_SQL_AUTO_INSTALL', true);\n";
        $dbConfig .= "define('BOT_SQL_MIRROR_FILES', false);\n";
        $dbConfig .= "define('DB_HOST', " . php_export_string($values['db_host']) . ");\n";
        $dbConfig .= "define('DB_NAME', " . php_export_string($values['db_name']) . ");\n";
        $dbConfig .= "define('DB_USER', " . php_export_string($values['db_user']) . ");\n";
        $dbConfig .= "define('DB_PASS', " . php_export_string($values['db_pass']) . ");\n";
        $dbConfig .= "define('DB_CHARSET', " . php_export_string($values['db_charset'] ?: 'utf8mb4') . ");\n";
        $dbConfig .= "?>\n";

        if (!write_php_file($root . '/config.php', $config)) $errors[] = 'نوشتن config.php ناموفق بود.';
        if (!write_php_file($root . '/config_db.php', $dbConfig)) $errors[] = 'نوشتن config_db.php ناموفق بود.';
        if (!$errors) {
            $cleanedSamples = cleanup_sample_config_files($root);
            $results[] = 'config.php و config_db.php ساخته شدند؛ دیگر نیازی به تغییر نام فایل‌های sample نیست.';
            if ($cleanedSamples) {
                $results[] = 'فایل‌های sample بعد از نصب پاک/غیرفعال شدند: ' . h(implode('، ', $cleanedSamples));
            }
        }

        if (!$errors && $sqlEnabled && $pdo instanceof PDO) {
            try {
                $schema = run_schema($pdo, $root . '/sql/schema.sql');
                if (empty($schema['ok'])) $errors[] = $schema['error'] ?? 'اجرای schema ناموفق بود.';
                else $results[] = 'جداول دیتابیس آماده شد. تعداد دستورهای اجراشده: ' . (int)$schema['count'];
            } catch (Throwable $e) {
                $errors[] = 'خطا در ساخت جدول‌ها: ' . $e->getMessage();
            }
        }

        if (!$errors) {
            install_runtime_defaults($root, $admin);
            $webAdminDataDir = $root . '/lib/kodam';
            if (!is_dir($webAdminDataDir)) @mkdir($webAdminDataDir, 0775, true);
            @file_put_contents($webAdminDataDir . '/data-web-admin.json', json_encode(['password_hash'=>$webPanelHash,'updated_at'=>date('c'),'version'=>'installer'], JSON_UNESCAPED_UNICODE|JSON_PRETTY_PRINT), LOCK_EX);
            if ($pdo instanceof PDO) {
                try {
                    $pdo->exec("CREATE TABLE IF NOT EXISTS bot_settings (setting_key VARCHAR(190) PRIMARY KEY, storage_value LONGTEXT NULL, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci");
                    $st = $pdo->prepare("INSERT INTO bot_settings(setting_key, storage_value) VALUES('web_admin_password_hash', ?) ON DUPLICATE KEY UPDATE storage_value=VALUES(storage_value)");
                    $st->execute([$webPanelHash]);
                } catch (Throwable $e) {}
            }
            $seededButtons = installer_seed_button_defaults($root, $pdo instanceof PDO ? $pdo : null);
            $results[] = 'فایل‌های اولیه، رمز پنل وب و کش تمیز ساخته شد.';
            $results[] = 'دکمه‌ها و چینش کامل منوی کاربر آماده شد. تعداد مقدارهای ثبت‌شده: ' . (int)$seededButtons;
            $results[] = 'پنل وب آماده است: ' . h($baseUrl . '/admin');
            @file_put_contents($lockFile, date('c') . PHP_EOL, LOCK_EX);

            if ($values['set_webhook'] === '1') {
                $webhook = $baseUrl . '/bot.php';
                $webhookResult = set_telegram_webhook($token, $webhook);
                if (!empty($webhookResult['ok'])) $results[] = 'وبهوک با موفقیت ست شد: ' . $webhook;
                else $results[] = 'نصب انجام شد، ولی ست وبهوک خطا داد: ' . h(json_encode($webhookResult, JSON_UNESCAPED_UNICODE));
            }
            $selfChecks = installer_self_test($root, $pdo instanceof PDO ? $pdo : null, $baseUrl, $token, $admin);
            $results[] = 'گزارش تست خودکار نصب:<br>' . installer_self_test_html($selfChecks);
        }
    }
}
?>
<!doctype html>
<html lang="fa" dir="rtl">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>نصب ربات تلگرام</title>
<style>
body{font-family:tahoma,Arial,sans-serif;background:#f6f7f9;color:#1f2937;margin:0;padding:24px;line-height:1.8}.box{max-width:980px;margin:0 auto;background:white;border-radius:16px;padding:24px;box-shadow:0 10px 30px rgba(0,0,0,.08)}h1{margin-top:0}.grid{display:grid;grid-template-columns:1fr 1fr;gap:14px}.field{display:flex;flex-direction:column;gap:6px}.field.full{grid-column:1/-1}label{font-weight:bold}input{padding:10px 12px;border:1px solid #cbd5e1;border-radius:10px;font-size:14px;direction:ltr}input[type=checkbox]{width:auto}.hint{font-size:12px;color:#64748b}.alert{padding:12px 14px;border-radius:12px;margin:12px 0}.err{background:#fee2e2;color:#991b1b}.ok{background:#dcfce7;color:#166534}.btn{border:0;background:#2563eb;color:white;padding:12px 18px;border-radius:12px;font-weight:bold;cursor:pointer}.code{background:#0f172a;color:#e2e8f0;border-radius:12px;padding:14px;direction:ltr;white-space:pre-wrap;overflow:auto}@media(max-width:760px){.grid{grid-template-columns:1fr}}
</style>
</head>
<body>
<div class="box">
<h1>نصب ربات تلگرام روی هاست جدید</h1>
<p>اطلاعات زیر را وارد کن. رمز بکاپ را هم همین‌جا مشخص کن. installer خودش <b>config.php</b> و <b>config_db.php</b> را می‌سازد؛ نیازی به تغییر نام فایل‌های sample نیست. بعد از نصب، برای امنیت فایل <b>install.php</b> را حذف کن.</p>

<?php if ($errors): ?>
<div class="alert err"><b>خطا:</b><ul><?php foreach ($errors as $e) echo '<li>'.h($e).'</li>'; ?></ul></div>
<?php endif; ?>
<?php if ($results): ?>
<div class="alert ok"><b>نتیجه:</b><ul><?php foreach ($results as $r) echo '<li>'.$r.'</li>'; ?></ul></div>
<div class="code">Cron Job پیشنهادی - Every Minute:
/usr/bin/curl -s "<?= h(rtrim($values['base_url'], '/')) ?>/cron_all_telegram.php?task=auto&broadcast_limit=20&broadcast_rps=20<?= $values['cron_secret'] !== '' ? '&key=' . h(rawurlencode($values['cron_secret'])) : '' ?>" &gt;/dev/null 2&gt;&amp;1

Webhook:
<?= h(rtrim($values['base_url'], '/')) ?>/bot.php</div>
<p><b>بعد از تست، install.php را حذف کن.</b></p>
<?php endif; ?>

<form method="post">
<div class="grid">
  <div class="field full"><label>توکن ربات تلگرام</label><input name="api_key" value="<?= h($values['api_key']) ?>" placeholder="123456:ABC..." required></div>
  <div class="field"><label>آیدی عددی ادمین اصلی</label><input name="admin_id" value="<?= h($values['admin_id']) ?>" placeholder="123456789" required></div>
  <div class="field"><label>یوزرنیم ربات بدون @</label><input name="bot_username" value="<?= h($values['bot_username']) ?>" placeholder="my_bot"></div>
  <div class="field full"><label>آدرس عمومی پوشه ربات</label><input name="base_url" value="<?= h($values['base_url']) ?>" placeholder="https://domain.com/telegram_bot" required><div class="hint">بدون / آخر. مثال: https://example.com/telegram_bot</div></div>

  <div class="field"><label>Merchant ID زرین‌پال</label><input name="zarinpal_merchant" value="<?= h($values['zarinpal_merchant']) ?>"></div>
  <div class="field"><label>واحد زرین‌پال</label><input name="zarinpal_currency" value="<?= h($values['zarinpal_currency']) ?>"></div>
  <div class="field full"><label><input type="checkbox" name="zarinpal_sandbox" value="1" <?= $values['zarinpal_sandbox']==='1'?'checked':'' ?>> حالت تست زرین‌پال فعال باشد</label></div>

  <div class="field full"><label><input type="checkbox" name="sql_enabled" value="1" <?= $values['sql_enabled']==='1'?'checked':'' ?>> ذخیره‌سازی دیتابیس فعال باشد</label></div>
  <div class="field"><label>DB Host</label><input name="db_host" value="<?= h($values['db_host']) ?>"></div>
  <div class="field"><label>DB Name</label><input name="db_name" value="<?= h($values['db_name']) ?>"></div>
  <div class="field"><label>DB User</label><input name="db_user" value="<?= h($values['db_user']) ?>"></div>
  <div class="field"><label>DB Password</label><input name="db_pass" value="<?= h($values['db_pass']) ?>"></div>
  <div class="field"><label>DB Charset</label><input name="db_charset" value="<?= h($values['db_charset']) ?>"></div>

  <div class="field"><label>رمز بکاپ دیتابیس</label><input name="backup_password" type="password" value="" placeholder="حداقل ۴ کاراکتر" required><div class="hint">برای ساخت بکاپ از پنل و دانلود فایل بکاپ لازم است.</div></div>
  <div class="field"><label>تکرار رمز بکاپ</label><input name="backup_password_confirm" type="password" value="" required></div>

  <div class="field full"><label>رمز اختیاری کرون</label><input name="cron_secret" value="<?= h($values['cron_secret']) ?>" placeholder="اختیاری"><div class="hint">اگر پر شود، کرون باید key را هم بفرستد.</div></div>
  <div class="field full"><label><input type="checkbox" name="set_webhook" value="1" <?= $values['set_webhook']==='1'?'checked':'' ?>> بعد از نصب وبهوک خودکار ست شود</label></div>
</div>
<p><button class="btn" type="submit">نصب و آماده‌سازی</button></p>
</form>

<hr>
<h3>پیش‌نیازها</h3>
<ul>
<li>PHP 8.0 به بالا</li>
<li>فعال بودن cURL</li>
<li>MySQL/MariaDB با دسترسی ساخت جدول</li>
<li>SSL معتبر، چون وبهوک تلگرام باید https باشد</li>
</ul>
</div>
</body>
</html>
