<?php
// Robust gift code service: SQL-first, legacy-file compatible.
// Handles both user redemption and admin management before the old legacy handlers run.

if (!function_exists('bot_gift_pdo')) {
function bot_gift_pdo(){ return function_exists('bot_sql_pdo') ? bot_sql_pdo() : null; }
}

if (!function_exists('bot_gift_json')) {
function bot_gift_json($data){ return json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); }
}

if (!function_exists('bot_gift_install_schema')) {
function bot_gift_install_schema(){
    $pdo = bot_gift_pdo();
    if(!$pdo) return false;
    try{
        $pdo->exec("CREATE TABLE IF NOT EXISTS bot_gift_codes (
            id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
            code VARCHAR(128) NOT NULL,
            amount INT NOT NULL DEFAULT 0,
            status VARCHAR(24) NOT NULL DEFAULT 'active',
            created_by VARCHAR(32) NULL,
            used_by VARCHAR(32) NULL,
            used_at TIMESTAMP NULL DEFAULT NULL,
            channel_ref VARCHAR(191) NULL,
            channel_message_id VARCHAR(64) NULL,
            published_at TIMESTAMP NULL DEFAULT NULL,
            data_json LONGTEXT NULL,
            created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
            updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
            UNIQUE KEY uniq_gift_code (code),
            KEY idx_gift_status (status),
            KEY idx_gift_used_by (used_by),
            KEY idx_gift_created (created_at)
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci");
        $pdo->exec("CREATE TABLE IF NOT EXISTS bot_gift_code_events (
            id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
            gift_id BIGINT UNSIGNED NULL,
            code VARCHAR(128) NOT NULL,
            actor_id VARCHAR(32) NULL,
            event_type VARCHAR(40) NOT NULL,
            amount INT NOT NULL DEFAULT 0,
            before_balance INT NULL,
            after_balance INT NULL,
            data_json LONGTEXT NULL,
            created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
            KEY idx_gift_event_code (code),
            KEY idx_gift_event_actor (actor_id),
            KEY idx_gift_event_type (event_type),
            KEY idx_gift_event_created (created_at)
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci");
        return true;
    }catch(Throwable $e){
        error_log('Gift schema install failed: '.$e->getMessage());
        return false;
    }
}
}

if (!function_exists('bot_gift_normalize_code')) {
function bot_gift_normalize_code($code){
    $code = trim((string)$code);
    $code = str_replace(["\r","\n","\t"], '', $code);
    $code = preg_replace('/\s+/u', '', $code);
    if(function_exists('bot_normalize_number_digits')) $code = bot_normalize_number_digits($code);
    return $code;
}
}

if (!function_exists('bot_gift_valid_code')) {
function bot_gift_valid_code($code){
    $code = bot_gift_normalize_code($code);
    if($code === '') return false;
    $len = function_exists('mb_strlen') ? mb_strlen($code, 'UTF-8') : strlen($code);
    if($len > 64) return false;
    if(strpos($code, '/') !== false || strpos($code, '\\') !== false || strpos($code, '..') !== false) return false;
    return (bool)preg_match('/^[\p{L}\p{N}_\-\.]+$/u', $code);
}
}

if (!function_exists('bot_gift_legacy_code_path')) {
function bot_gift_legacy_code_path($code){
    $code = bot_gift_normalize_code($code);
    if(!bot_gift_valid_code($code)) return '';
    return 'lib/others/codes/'.$code.'.txt';
}
}

if (!function_exists('bot_gift_fallback_file')) {
function bot_gift_fallback_file(){ return 'cache/gift_codes.json'; }
}
if (!function_exists('bot_gift_fallback_load')) {
function bot_gift_fallback_load(){
    $f = bot_gift_fallback_file();
    $v = is_file($f) ? json_decode((string)@file_get_contents($f), true) : [];
    return is_array($v) ? $v : [];
}
}
if (!function_exists('bot_gift_fallback_save')) {
function bot_gift_fallback_save(array $data){
    if(!is_dir('cache')) @mkdir('cache', 0775, true);
    @file_put_contents(bot_gift_fallback_file(), bot_gift_json($data), LOCK_EX);
}
}

if (!function_exists('bot_gift_event')) {
function bot_gift_event($giftId, $code, $actorId, $type, $amount = 0, $before = null, $after = null, array $extra = []){
    $pdo = bot_gift_pdo();
    if($pdo){
        try{
            $st = $pdo->prepare('INSERT INTO bot_gift_code_events (gift_id, code, actor_id, event_type, amount, before_balance, after_balance, data_json) VALUES (?,?,?,?,?,?,?,?)');
            $st->execute([$giftId ?: null, (string)$code, (string)$actorId, (string)$type, (int)$amount, $before, $after, bot_gift_json($extra)]);
        }catch(Throwable $e){ error_log('Gift event failed: '.$e->getMessage()); }
    }
}
}

if (!function_exists('bot_gift_migrate_legacy_codes')) {
function bot_gift_migrate_legacy_codes(){
    $pdo = bot_gift_pdo();
    if(!$pdo) return 0;
    bot_gift_install_schema();
    $dir = 'lib/others/codes';
    if(!is_dir($dir)) return 0;
    $count = 0;
    $st = $pdo->prepare("INSERT IGNORE INTO bot_gift_codes (code, amount, status, created_by, data_json) VALUES (?,?,?,?,?)");
    foreach(scandir($dir) ?: [] as $file){
        if($file === '.' || $file === '..' || !preg_match('/^(.+)\.txt$/u', $file, $m)) continue;
        $code = bot_gift_normalize_code($m[1]);
        if(!bot_gift_valid_code($code)) continue;
        $amount = (int)trim((string)@file_get_contents($dir.'/'.$file));
        if($amount <= 0) continue;
        $st->execute([$code, $amount, 'active', 'legacy', bot_gift_json(['migrated_from'=>'legacy_file','file'=>$file,'time'=>time()])]);
        $count += (int)$st->rowCount();
    }
    return $count;
}
}

if (!function_exists('bot_gift_get_by_id')) {
function bot_gift_get_by_id($id){
    $pdo = bot_gift_pdo();
    if($pdo){
        bot_gift_install_schema();
        $st = $pdo->prepare('SELECT * FROM bot_gift_codes WHERE id=? LIMIT 1');
        $st->execute([(int)$id]);
        $row = $st->fetch();
        return $row ?: null;
    }
    $all = bot_gift_fallback_load();
    foreach($all as $code=>$row){ if((string)($row['id'] ?? '') === (string)$id) return $row + ['code'=>$code]; }
    return null;
}
}

if (!function_exists('bot_gift_get_by_code')) {
function bot_gift_get_by_code($code){
    $code = bot_gift_normalize_code($code);
    if(!bot_gift_valid_code($code)) return null;
    $pdo = bot_gift_pdo();
    if($pdo){
        bot_gift_install_schema();
        bot_gift_migrate_legacy_codes();
        $st = $pdo->prepare('SELECT * FROM bot_gift_codes WHERE code=? LIMIT 1');
        $st->execute([$code]);
        $row = $st->fetch();
        return $row ?: null;
    }
    $all = bot_gift_fallback_load();
    if(isset($all[$code])) return $all[$code] + ['code'=>$code];
    $legacy = bot_gift_legacy_code_path($code);
    if($legacy !== '' && is_file($legacy)) return ['id'=>0,'code'=>$code,'amount'=>(int)trim((string)@file_get_contents($legacy)),'status'=>'active'];
    return null;
}
}

if (!function_exists('bot_gift_create_code')) {
function bot_gift_create_code($code, $amount, $adminId){
    $code = bot_gift_normalize_code($code);
    $amount = (int)$amount;
    if(!bot_gift_valid_code($code)) return ['ok'=>false,'error'=>'invalid_code'];
    if($amount <= 0) return ['ok'=>false,'error'=>'invalid_amount'];
    if($amount > 100000000) return ['ok'=>false,'error'=>'amount_too_large'];

    $pdo = bot_gift_pdo();
    if($pdo){
        bot_gift_install_schema();
        bot_gift_migrate_legacy_codes();
        try{
            $st = $pdo->prepare('INSERT INTO bot_gift_codes (code, amount, status, created_by, data_json) VALUES (?,?,?,?,?)');
            $st->execute([$code, $amount, 'active', (string)$adminId, bot_gift_json(['created_from'=>'admin_panel','time'=>time()])]);
            $id = (int)$pdo->lastInsertId();
            bot_gift_event($id, $code, $adminId, 'created', $amount);
        }catch(Throwable $e){
            if(stripos($e->getMessage(), 'Duplicate') !== false || stripos($e->getMessage(), 'Integrity constraint') !== false){
                return ['ok'=>false,'error'=>'duplicate'];
            }
            return ['ok'=>false,'error'=>'db_error','detail'=>$e->getMessage()];
        }
    }else{
        $all = bot_gift_fallback_load();
        if(isset($all[$code]) && ($all[$code]['status'] ?? 'active') === 'active') return ['ok'=>false,'error'=>'duplicate'];
        $id = time().rand(100,999);
        $all[$code] = ['id'=>$id,'code'=>$code,'amount'=>$amount,'status'=>'active','created_by'=>(string)$adminId,'created_at'=>date('Y-m-d H:i:s')];
        bot_gift_fallback_save($all);
    }

    $legacy = bot_gift_legacy_code_path($code);
    if($legacy !== ''){
        $dir = dirname($legacy); if(!is_dir($dir)) @mkdir($dir, 0775, true);
        @file_put_contents($legacy, (string)$amount, LOCK_EX);
    }
    return ['ok'=>true,'id'=>$id,'code'=>$code,'amount'=>$amount];
}
}

if (!function_exists('bot_gift_add_points')) {
function bot_gift_add_points($targetUserId, $amount, $reason = 'gift_code', array $extra = [], $pdoInTransaction = null){
    $amount = (int)$amount;
    if($amount <= 0) return ['ok'=>false,'error'=>'bad_amount'];

    // اگر مصرف کد هدیه داخل تراکنش دیتابیس انجام می‌شود، شارژ حساب هم باید در همان تراکنش باشد.
    // این کار جلوی باطل شدن کد بدون شارژ شدن موجودی را می‌گیرد.
    if($pdoInTransaction instanceof PDO && $pdoInTransaction->inTransaction() && function_exists('bot_wallet_get_user_for_update') && function_exists('bot_wallet_save_user')){
        try{
            $u = bot_wallet_get_user_for_update($pdoInTransaction, $targetUserId);
            if(!is_array($u)) $u = [];
            $before = (int)($u['Points'] ?? 0);
            $after = max(0, $before + $amount);
            $u['Points'] = $after;
            if($reason !== '') $u['wallet_log'][] = ['time'=>time(), 'reason'=>$reason, 'delta'=>$amount, 'before'=>$before, 'after'=>$after] + $extra;
            bot_wallet_save_user($pdoInTransaction, $targetUserId, $u);
            if(function_exists('bot_cache_invalidate_for_path')) bot_cache_invalidate_for_path('melat/'.$targetUserId.'.json');
            return ['ok'=>true,'before'=>$before,'after'=>$after,'delta'=>$amount,'data'=>$u,'same_transaction'=>true];
        }catch(Throwable $e){
            return ['ok'=>false,'error'=>'wallet_tx_error','detail'=>$e->getMessage()];
        }
    }

    if(function_exists('bot_simple_add_points_to_user')){
        $res = bot_simple_add_points_to_user($targetUserId, $amount, $reason, $extra);
        if(is_array($res) && !empty($res['ok'])) return $res;
        return is_array($res) ? ($res + ['ok'=>false]) : ['ok'=>false,'error'=>'wallet_add_failed'];
    }
    if(function_exists('bot_wallet_add')){
        $res = bot_wallet_add($targetUserId, $amount, $reason, $extra);
        if(is_array($res) && !empty($res['ok'])) return $res;
        return is_array($res) ? ($res + ['ok'=>false]) : ['ok'=>false,'error'=>'wallet_add_failed'];
    }

    $u = function_exists('bot_data_get_json') ? bot_data_get_json('melat/'.$targetUserId.'.json', []) : [];
    if(!is_array($u)) $u = [];
    $before = (int)($u['Points'] ?? 0);
    $after = $before + $amount;
    $u['Points'] = $after;
    if($reason !== '') $u['wallet_log'][] = ['time'=>time(), 'reason'=>$reason, 'delta'=>$amount, 'before'=>$before, 'after'=>$after] + $extra;
    if(function_exists('saveJson')) saveJson('melat/'.$targetUserId.'.json', $u);
    elseif(function_exists('bot_data_put_json')) bot_data_put_json('melat/'.$targetUserId.'.json', $u);
    else return ['ok'=>false,'error'=>'no_storage'];
    return ['ok'=>true,'before'=>$before,'after'=>$after,'delta'=>$amount,'data'=>$u];
}
}

if (!function_exists('bot_gift_redeem_code')) {
function bot_gift_redeem_code($code, $userId){
    $code = bot_gift_normalize_code($code);
    if(!bot_gift_valid_code($code)) return ['ok'=>false,'error'=>'invalid'];
    $pdo = bot_gift_pdo();
    if($pdo){
        bot_gift_install_schema();
        bot_gift_migrate_legacy_codes();
        try{
            $pdo->beginTransaction();
            $st = $pdo->prepare('SELECT * FROM bot_gift_codes WHERE code=? LIMIT 1 FOR UPDATE');
            $st->execute([$code]);
            $row = $st->fetch();
            if(!$row){ $pdo->rollBack(); return ['ok'=>false,'error'=>'not_found']; }
            if((string)$row['status'] !== 'active'){
                $pdo->rollBack();
                return ['ok'=>false,'error'=>((string)$row['status'] === 'used' ? 'used' : 'disabled')];
            }
            $amount = (int)$row['amount'];
            if($amount <= 0){ $pdo->rollBack(); return ['ok'=>false,'error'=>'bad_amount']; }
            $add = bot_gift_add_points($userId, $amount, 'gift_code', ['code'=>$code,'gift_id'=>(int)$row['id']], $pdo);
            if(!is_array($add) || empty($add['ok'])){
                $pdo->rollBack();
                return ['ok'=>false,'error'=>'wallet_add_failed','detail'=>is_array($add) ? ($add['detail'] ?? $add['error'] ?? '') : ''];
            }
            $before = isset($add['before']) ? (int)$add['before'] : null;
            $after = isset($add['after']) ? (int)$add['after'] : null;
            $up = $pdo->prepare("UPDATE bot_gift_codes SET status='used', used_by=?, used_at=CURRENT_TIMESTAMP, updated_at=CURRENT_TIMESTAMP WHERE id=? AND status='active'");
            $up->execute([(string)$userId, (int)$row['id']]);
            bot_gift_event((int)$row['id'], $code, $userId, 'redeemed', $amount, $before, $after);
            $pdo->commit();
            if(function_exists('bot_ledger_record')) bot_ledger_record($userId, 'diamond', $amount, $before, $after, 'gift_code', ['gift_code'=>$code,'gift_id'=>(int)$row['id']]);
            $legacy = bot_gift_legacy_code_path($code); if($legacy !== '' && is_file($legacy)) @unlink($legacy);
            return ['ok'=>true,'code'=>$code,'amount'=>$amount,'before'=>$before,'after'=>$after,'gift_id'=>(int)$row['id']];
        }catch(Throwable $e){
            if($pdo->inTransaction()) $pdo->rollBack();
            return ['ok'=>false,'error'=>'db_error','detail'=>$e->getMessage()];
        }
    }

    $all = bot_gift_fallback_load();
    if(isset($all[$code])){
        if(($all[$code]['status'] ?? 'active') !== 'active') return ['ok'=>false,'error'=>'used'];
        $amount = (int)($all[$code]['amount'] ?? 0);
        if($amount <= 0) return ['ok'=>false,'error'=>'bad_amount'];
        $add = bot_gift_add_points($userId, $amount, 'gift_code', ['code'=>$code]);
        if(!is_array($add) || empty($add['ok'])) return ['ok'=>false,'error'=>'wallet_add_failed','detail'=>is_array($add) ? ($add['detail'] ?? $add['error'] ?? '') : ''];
        $all[$code]['status'] = 'used';
        $all[$code]['used_by'] = (string)$userId;
        $all[$code]['used_at'] = date('Y-m-d H:i:s');
        bot_gift_fallback_save($all);
        $legacy = bot_gift_legacy_code_path($code); if($legacy !== '' && is_file($legacy)) @unlink($legacy);
        return ['ok'=>true,'code'=>$code,'amount'=>$amount,'before'=>$add['before'] ?? null,'after'=>$add['after'] ?? null];
    }
    $legacy = bot_gift_legacy_code_path($code);
    if($legacy !== '' && is_file($legacy)){
        $amount = (int)trim((string)@file_get_contents($legacy));
        if($amount <= 0) return ['ok'=>false,'error'=>'bad_amount'];
        $add = bot_gift_add_points($userId, $amount, 'gift_code', ['code'=>$code,'legacy'=>true]);
        if(!is_array($add) || empty($add['ok'])) return ['ok'=>false,'error'=>'wallet_add_failed','detail'=>is_array($add) ? ($add['detail'] ?? $add['error'] ?? '') : ''];
        @unlink($legacy);
        return ['ok'=>true,'code'=>$code,'amount'=>$amount,'before'=>$add['before'] ?? null,'after'=>$add['after'] ?? null];
    }
    return ['ok'=>false,'error'=>'not_found'];
}
}

if (!function_exists('bot_gift_counts')) {
function bot_gift_counts(){
    $pdo = bot_gift_pdo();
    $out = ['active'=>0,'used'=>0,'disabled'=>0,'total'=>0];
    if($pdo){
        bot_gift_install_schema();
        try{
            foreach($pdo->query('SELECT status, COUNT(*) c FROM bot_gift_codes GROUP BY status') as $r){
                $status = (string)$r['status']; $out[$status] = (int)$r['c']; $out['total'] += (int)$r['c'];
            }
        }catch(Throwable $e){}
        return $out;
    }
    $all = bot_gift_fallback_load();
    foreach($all as $r){ $s=(string)($r['status'] ?? 'active'); if(!isset($out[$s])) $out[$s]=0; $out[$s]++; $out['total']++; }
    return $out;
}
}

if (!function_exists('bot_gift_recent_rows')) {
function bot_gift_recent_rows($limit = 10){
    $limit = max(1, min(20, (int)$limit));
    $pdo = bot_gift_pdo();
    if($pdo){
        bot_gift_install_schema();
        $st = $pdo->query('SELECT * FROM bot_gift_codes ORDER BY id DESC LIMIT '.$limit);
        return $st ? $st->fetchAll() : [];
    }
    $all = bot_gift_fallback_load();
    $rows = [];
    foreach(array_reverse($all, true) as $code=>$r){ $rows[] = $r + ['code'=>$code]; if(count($rows)>=$limit) break; }
    return $rows;
}
}

if (!function_exists('bot_gift_channel_ref')) {
function bot_gift_channel_ref(){ return trim((string)(function_exists('bot_data_get_text') ? bot_data_get_text('lib/kodam/giftch.txt', '') : (is_file('lib/kodam/giftch.txt') ? @file_get_contents('lib/kodam/giftch.txt') : ''))); }
}
if (!function_exists('bot_gift_channel_display')) {
function bot_gift_channel_display(){
    $ch = bot_gift_channel_ref();
    if($ch === '') return 'تنظیم نشده';
    if(function_exists('bale_channel_display_name')) return bale_channel_display_name($ch);
    return preg_match('/^-?\d+$/', $ch) ? $ch : '@'.ltrim($ch,'@');
}
}
if (!function_exists('bot_gift_channel_chat_id')) {
function bot_gift_channel_chat_id($channelRef){
    $channelRef = trim((string)$channelRef);
    if($channelRef === '') return '';
    if(function_exists('normalize_bale_channel_username')) $channelRef = normalize_bale_channel_username($channelRef);
    if(preg_match('/^-?\d{5,30}$/', $channelRef)) return $channelRef;
    return '@'.ltrim($channelRef, '@');
}
}

if (!function_exists('bot_gift_admin_text')) {
function bot_gift_admin_text(){
    global $money;
    bot_gift_install_schema();
    bot_gift_migrate_legacy_codes();
    $c = bot_gift_counts();
    return "🎉 **پنل کد هدیه**\n\n".
        "🎁 کانال کد هدیه: **".bot_gift_channel_display()."**\n".
        "✅ کدهای فعال: **".number_format((int)($c['active'] ?? 0))."**\n".
        "☑️ استفاده‌شده: **".number_format((int)($c['used'] ?? 0))."**\n".
        "🚫 غیرفعال: **".number_format((int)($c['disabled'] ?? 0))."**\n\n".
        "از همین بخش کد هدیه بساز، بفرست داخل کانال و وضعیت استفاده‌شدن کدها را ببین. پاداش هم با واحد **{$money}** به حساب کاربر اضافه می‌شود.";
}
}
if (!function_exists('bot_gift_admin_keyboard')) {
function bot_gift_admin_keyboard(){
    return json_encode(['inline_keyboard'=>[
        [[ 'text'=>'➕ ساخت کد هدیه', 'callback_data'=>'gift_admin_create' ], [ 'text'=>'📋 آخرین کدها', 'callback_data'=>'gift_admin_list' ]],
        [[ 'text'=>'📣 تنظیم کانال کد هدیه', 'callback_data'=>'gift_admin_set_channel' ], [ 'text'=>'🗑 حذف کانال کد هدیه', 'callback_data'=>'gift_admin_delete_channel' ]],
        [[ 'text'=>'🔙 بازگشت به پنل ادمین', 'callback_data'=>'admin_main_menu' ]],
    ]], JSON_UNESCAPED_UNICODE);
}
}
if (!function_exists('bot_gift_user_keyboard')) {
function bot_gift_user_keyboard(){
    return json_encode(['keyboard'=>[[['text'=>'🔙بازگشت به منو']]], 'resize_keyboard'=>true, 'one_time_keyboard'=>true], JSON_UNESCAPED_UNICODE);
}
}
if (!function_exists('bot_gift_back_to_admin_keyboard')) {
function bot_gift_back_to_admin_keyboard($id = 0){
    $rows = [];
    if($id) $rows[] = [[ 'text'=>'📣 ارسال به کانال کد هدیه', 'callback_data'=>'gift_publish_'.$id ]];
    $rows[] = [[ 'text'=>'🎉 پنل کد هدیه', 'callback_data'=>'gift_admin_panel' ]];
    return json_encode(['inline_keyboard'=>$rows], JSON_UNESCAPED_UNICODE);
}
}

if (!function_exists('bot_gift_list_text')) {
function bot_gift_list_text(){
    global $money;
    $rows = bot_gift_recent_rows(10);
    if(empty($rows)) return "📋 **آخرین کدهای هدیه**\n\nهنوز کدی ساخته نشده است.";
    $lines = ["📋 **آخرین کدهای هدیه**"];
    foreach($rows as $r){
        $status = (string)($r['status'] ?? 'active');
        $s = $status === 'active' ? '✅ فعال' : ($status === 'used' ? '☑️ استفاده‌شده' : '🚫 غیرفعال');
        $used = !empty($r['used_by']) ? ' | کاربر: '.$r['used_by'] : '';
        $lines[] = "\n#".($r['id'] ?? '-')." | **".($r['code'] ?? '')."** | ".number_format((int)($r['amount'] ?? 0))." {$money} | {$s}{$used}";
    }
    return implode('', $lines);
}
}

if (!function_exists('bot_gift_user_button_match')) {
function bot_gift_user_button_match($msg){
    global $dok0;
    $msg = trim((string)$msg);
    $labels = ['🎁 کد هـدیـه','🎁 کد هدیه','کد هدیه','🎉 کد هدیه'];
    if(isset($dok0) && trim((string)$dok0) !== '') $labels[] = trim((string)$dok0);
    return in_array($msg, array_values(array_unique($labels)), true);
}
}

if (!function_exists('bot_gift_publish_to_channel')) {
function bot_gift_publish_to_channel($id, $adminId){
    global $money, $boter_id;
    $row = bot_gift_get_by_id($id);
    if(!$row) return ['ok'=>false,'error'=>'not_found'];
    if((string)($row['status'] ?? '') !== 'active') return ['ok'=>false,'error'=>'not_active'];
    $channel = bot_gift_channel_ref();
    if($channel === '') return ['ok'=>false,'error'=>'channel_missing'];
    $chatId = bot_gift_channel_chat_id($channel);
    $botUrl = trim((string)$boter_id) !== '' ? 'https://t.me/'.ltrim((string)$boter_id, '@') : 'https://t.me/';
    $text = "🎁 کد هدیه جدید ساخته شد\n\n".
            "🏷 کد: ".(string)$row['code']."\n".
            "💎 مقدار: ".number_format((int)$row['amount'])." {$money}\n\n".
            "هرکس زودتر این کد را در بخش کد هدیه ربات وارد کند، پاداش را دریافت می‌کند.";
    $res = bot('sendMessage', [
        'chat_id'=>$chatId,
        'text'=>$text,
        'reply_markup'=>json_encode(['inline_keyboard'=>[[['text'=>'🤖 ورود به ربات','url'=>$botUrl]]]], JSON_UNESCAPED_UNICODE)
    ]);
    $ok = isset($res->ok) ? (bool)$res->ok : false;
    if(!$ok) return ['ok'=>false,'error'=>'send_failed','description'=>$res->description ?? 'unknown'];
    $msgId = isset($res->result->message_id) ? (string)$res->result->message_id : '';
    $pdo = bot_gift_pdo();
    if($pdo){
        try{
            $st = $pdo->prepare('UPDATE bot_gift_codes SET channel_ref=?, channel_message_id=?, published_at=CURRENT_TIMESTAMP WHERE id=?');
            $st->execute([(string)$channel, $msgId, (int)$id]);
        }catch(Throwable $e){}
    }
    bot_gift_event((int)$id, (string)$row['code'], $adminId, 'published', (int)$row['amount'], null, null, ['channel'=>$channel,'message_id'=>$msgId]);
    return ['ok'=>true,'message_id'=>$msgId];
}
}

if (!function_exists('bot_gift_save_channel_from_message')) {
function bot_gift_save_channel_from_message($message, $chatID, &$user, $userID){
    $channel = function_exists('bale_extract_channel_ref_from_message') ? bale_extract_channel_ref_from_message($message) : (isset($message->text) ? trim((string)$message->text) : '');
    if(function_exists('normalize_bale_channel_username')) $channel = normalize_bale_channel_username($channel);
    if($channel === '' || (function_exists('is_valid_bale_channel_username') && !is_valid_bale_channel_username($channel))){
        if(function_exists('send_channel_username_error')) send_channel_username_error($chatID);
        else bot('sendMessage',['chat_id'=>$chatID,'text'=>'❌ آیدی کانال نامعتبر است.']);
        return false;
    }
    if(function_exists('bot_data_put_text')) bot_data_put_text('lib/kodam/giftch.txt', $channel); else @file_put_contents('lib/kodam/giftch.txt', $channel);
    $user['step'] = 'none';
    if(function_exists('saveJson')) saveJson('melat/'.$userID.'.json', $user);
    $checkText = '';
    if(function_exists('bale_bot_channel_status')){
        $check = bale_bot_channel_status($channel);
        if(!empty($check['admin'])) $checkText = "✅ ربات در کانال ادمین است.";
        else $checkText = "⚠️ کانال ذخیره شد ولی ادمین بودن ربات تأیید نشد. ربات را در کانال ادمین کن تا ارسال کد هدیه به کانال بدون خطا انجام شود.";
    }
    bot('sendMessage',[
        'chat_id'=>$chatID,
        'text'=>"✅ کانال کد هدیه تنظیم شد: **".bot_gift_channel_display()."**\n{$checkText}\n\n".bot_gift_admin_text(),
        'parse_mode'=>'MarkDown',
        'reply_markup'=>bot_gift_admin_keyboard()
    ]);
    return true;
}
}

if (!function_exists('bot_gift_runtime_router')) {
function bot_gift_runtime_router(){
    global $msg, $data, $Tc, $isAdmin, $chatID, $userID, $user, $step, $msg_id, $data_id, $message, $Button_Home, $money, $admin;
    if(!isset($Tc) || (string)$Tc !== 'private') return false;
    $step = isset($step) ? (string)$step : (string)($user['step'] ?? 'none');
    $isCallback = isset($data) && $data !== null && (string)$data !== '';

    // Admin callbacks
    if($isCallback && $isAdmin && preg_match('/^gift_/', (string)$data)){
        if(isset($data_id)) bot('answercallbackquery', ['callback_query_id'=>$data_id, 'text'=>'', 'show_alert'=>false]);
        if((string)$data === 'gift_admin_panel'){
            bot('editMessageText', ['chat_id'=>$chatID, 'message_id'=>$msg_id, 'text'=>bot_gift_admin_text(), 'parse_mode'=>'MarkDown', 'reply_markup'=>bot_gift_admin_keyboard()]);
            return true;
        }
        if((string)$data === 'gift_admin_create'){
            $user['step'] = 'gift_admin_wait_code';
            if(function_exists('saveJson')) saveJson('melat/'.$userID.'.json', $user);
            bot('sendMessage', ['chat_id'=>$chatID, 'text'=>"🎁 کد هدیه را وارد کنید.\n\nفقط حروف، عدد، خط تیره، نقطه و آندرلاین مجاز است.\nمثال: **VIP1403**", 'parse_mode'=>'MarkDown', 'reply_markup'=>bot_gift_user_keyboard()]);
            return true;
        }
        if((string)$data === 'gift_admin_set_channel'){
            $user['step'] = 'gift_admin_wait_channel';
            if(function_exists('saveJson')) saveJson('melat/'.$userID.'.json', $user);
            bot('sendMessage', ['chat_id'=>$chatID, 'text'=>"📣 آیدی یا لینک کانال کد هدیه را بفرست.\n\nقبول می‌شود: @channel، channel، لینک t.me/channel یا فوروارد یک پیام از کانال.\n⚠️ ربات باید در کانال ادمین باشد.", 'parse_mode'=>'MarkDown', 'reply_markup'=>bot_gift_user_keyboard()]);
            return true;
        }
        if((string)$data === 'gift_admin_delete_channel'){
            if(function_exists('bot_data_put_text')) bot_data_put_text('lib/kodam/giftch.txt', ''); else @file_put_contents('lib/kodam/giftch.txt', '');
            bot('editMessageText', ['chat_id'=>$chatID, 'message_id'=>$msg_id, 'text'=>"✅ کانال کد هدیه حذف شد.\n\n".bot_gift_admin_text(), 'parse_mode'=>'MarkDown', 'reply_markup'=>bot_gift_admin_keyboard()]);
            return true;
        }
        if((string)$data === 'gift_admin_list'){
            bot('editMessageText', ['chat_id'=>$chatID, 'message_id'=>$msg_id, 'text'=>bot_gift_list_text(), 'parse_mode'=>'MarkDown', 'reply_markup'=>bot_gift_back_to_admin_keyboard()]);
            return true;
        }
        if(preg_match('/^gift_publish_(\d+)$/', (string)$data, $m)){
            $res = bot_gift_publish_to_channel((int)$m[1], $userID);
            if(empty($res['ok'])){
                $err = (string)($res['error'] ?? 'unknown');
                $msgErr = '❌ ارسال به کانال انجام نشد.';
                if($err === 'channel_missing') $msgErr .= "\nکانال کد هدیه هنوز تنظیم نشده است.";
                elseif($err === 'not_active') $msgErr .= "\nاین کد دیگر فعال نیست.";
                elseif($err === 'send_failed') $msgErr .= "\nخطای تلگرام: ".(string)($res['description'] ?? 'نامشخص');
                bot('sendMessage', ['chat_id'=>$chatID, 'text'=>$msgErr, 'parse_mode'=>'HTML', 'reply_markup'=>bot_gift_admin_keyboard()]);
                return true;
            }
            bot('editMessageText', ['chat_id'=>$chatID, 'message_id'=>$msg_id, 'text'=>"✅ کد هدیه به کانال ارسال شد.\n\n".bot_gift_admin_text(), 'parse_mode'=>'MarkDown', 'reply_markup'=>bot_gift_admin_keyboard()]);
            return true;
        }
    }

    // Admin text entry
    if(isset($msg) && $isAdmin && trim((string)$msg) === '🎉 کد هدیه'){
        $user['step'] = 'none';
        if(function_exists('saveJson')) saveJson('melat/'.$userID.'.json', $user);
        bot('sendMessage', ['chat_id'=>$chatID, 'text'=>bot_gift_admin_text(), 'parse_mode'=>'MarkDown', 'reply_markup'=>bot_gift_admin_keyboard()]);
        return true;
    }
    if(isset($msg) && $isAdmin && in_array(trim((string)$msg), ['🎁تنظیم کانال کدهدیه','🎁 تنظیم کانال کد هدیه','تنظیم کانال کد هدیه'], true)){
        $user['step'] = 'gift_admin_wait_channel';
        if(function_exists('saveJson')) saveJson('melat/'.$userID.'.json', $user);
        bot('sendMessage', ['chat_id'=>$chatID, 'text'=>'📣 آیدی یا لینک کانال کد هدیه را ارسال کنید. ربات باید ادمین کانال باشد.', 'parse_mode'=>'HTML', 'reply_markup'=>bot_gift_user_keyboard()]);
        return true;
    }
    if($isAdmin && $step === 'gift_admin_wait_channel' && isset($msg) && !bot_is_menu_back_text($msg)){
        return bot_gift_save_channel_from_message($message, $chatID, $user, $userID);
    }
    if($isAdmin && $step === 'gift_admin_wait_code' && isset($msg) && !bot_is_menu_back_text($msg)){
        $code = bot_gift_normalize_code($msg);
        if(!bot_gift_valid_code($code)){
            bot('sendMessage', ['chat_id'=>$chatID, 'text'=>'❌ کد نامعتبر است. فقط حروف، عدد، خط تیره، نقطه و آندرلاین بفرست.', 'parse_mode'=>'HTML', 'reply_markup'=>bot_gift_user_keyboard()]);
            return true;
        }
        $user['step'] = 'gift_admin_wait_amount|'.$code;
        if(function_exists('saveJson')) saveJson('melat/'.$userID.'.json', $user);
        bot('sendMessage', ['chat_id'=>$chatID, 'text'=>"💎 مقدار {$money} این کد را عددی وارد کنید.\n\nکد: **{$code}**", 'parse_mode'=>'MarkDown', 'reply_markup'=>bot_gift_user_keyboard()]);
        return true;
    }
    if($isAdmin && preg_match('/^gift_admin_wait_amount\|(.+)$/', $step, $m) && isset($msg) && !bot_is_menu_back_text($msg)){
        $amountRaw = function_exists('bot_normalize_number_digits') ? bot_normalize_number_digits($msg) : (string)$msg;
        $amountRaw = preg_replace('/[^0-9]/', '', $amountRaw);
        $amount = (int)$amountRaw;
        if($amount <= 0){
            bot('sendMessage', ['chat_id'=>$chatID, 'text'=>'❌ فقط عدد مثبت وارد کنید.', 'parse_mode'=>'HTML', 'reply_markup'=>bot_gift_user_keyboard()]);
            return true;
        }
        $res = bot_gift_create_code($m[1], $amount, $userID);
        $user['step'] = 'none';
        if(function_exists('saveJson')) saveJson('melat/'.$userID.'.json', $user);
        if(empty($res['ok'])){
            $err = (string)($res['error'] ?? 'unknown');
            $text = $err === 'duplicate' ? '❌ این کد قبلاً ساخته شده است. کد دیگری انتخاب کن.' : '❌ ساخت کد انجام نشد. خطا: '.$err;
            bot('sendMessage', ['chat_id'=>$chatID, 'text'=>$text, 'parse_mode'=>'HTML', 'reply_markup'=>bot_gift_admin_keyboard()]);
            return true;
        }
        $id = (int)$res['id'];
        $text = "✅ کد هدیه ساخته شد.\n\n".
                "🏷 کد: **{$res['code']}**\n".
                "💎 مقدار: **".number_format((int)$res['amount'])." {$money}**\n".
                "📣 کانال کد هدیه: **".bot_gift_channel_display()."**\n\n".
                "برای ارسال در کانال، دکمه زیر را بزن.";
        bot('sendMessage', ['chat_id'=>$chatID, 'text'=>$text, 'parse_mode'=>'MarkDown', 'reply_markup'=>bot_gift_back_to_admin_keyboard($id)]);
        return true;
    }

    // User side
    if(isset($msg) && !$isAdmin && bot_gift_user_button_match($msg)){
        $user['step'] = 'gift_user_wait_code';
        if(function_exists('saveJson')) saveJson('melat/'.$userID.'.json', $user);
        $prompt = function_exists('bot_text_settings_get') ? bot_text_settings_get('doktxt0') : '';
        if(trim($prompt) === '') $prompt = '🎁 کد هدیه را بفرست تا برات ثبت کنم.';
        bot('sendMessage', ['chat_id'=>$chatID, 'text'=>$prompt, 'parse_mode'=>'MarkDown', 'reply_to_message_id'=>$msg_id, 'reply_markup'=>bot_gift_user_keyboard()]);
        return true;
    }
    if(isset($msg) && $isAdmin && bot_gift_user_button_match($msg)){
        // If an admin presses the user-side gift button, open the admin gift panel instead of redeem flow.
        $user['step'] = 'none';
        if(function_exists('saveJson')) saveJson('melat/'.$userID.'.json', $user);
        bot('sendMessage', ['chat_id'=>$chatID, 'text'=>bot_gift_admin_text(), 'parse_mode'=>'MarkDown', 'reply_markup'=>bot_gift_admin_keyboard()]);
        return true;
    }
    if(in_array($step, ['gift_user_wait_code', 'giftcodesnew'], true) && isset($msg) && !bot_is_menu_back_text($msg)){
        $res = bot_gift_redeem_code($msg, $userID);
        if(!empty($res['ok'])){
            $after = isset($res['after']) ? (int)$res['after'] : (int)(function_exists('bot_data_get_json') ? (bot_data_get_json('melat/'.$userID.'.json', [])['Points'] ?? 0) : 0);
            // مهم: بعد از شارژ، step را با همان موجودی جدید ذخیره می‌کنیم تا saveJson موجودی را به مقدار قدیمی برنگرداند.
            $user['Points'] = $after;
            $user['step'] = 'none';
            if(function_exists('saveJson')) saveJson('melat/'.$userID.'.json', $user);
            bot('sendMessage', ['chat_id'=>$chatID, 'text'=>"✅ تبریک!\nکد هدیه صحیح بود و **".number_format((int)$res['amount'])." {$money}** به حساب شما اضافه شد.\nموجودی فعلی: **".number_format($after)." {$money}**", 'parse_mode'=>'MarkDown', 'reply_markup'=>function_exists('bot_home_build_reply_keyboard') ? bot_home_build_reply_keyboard(false) : $Button_Home]);
            $giftch = bot_gift_channel_ref();
            if(trim($giftch) !== ''){
                $chat = bot_gift_channel_chat_id($giftch);
                bot('sendMessage', ['chat_id'=>$chat, 'text'=>"✅ کد هدیه **".bot_gift_normalize_code($msg)."** استفاده شد.\n👤 کاربر: **{$userID}**\n💎 مقدار: **".number_format((int)$res['amount'])." {$money}**", 'parse_mode'=>'MarkDown']);
            }
            return true;
        }
        $user['step'] = 'none';
        if(function_exists('saveJson')) saveJson('melat/'.$userID.'.json', $user);
        $err = (string)($res['error'] ?? 'invalid');
        if($err === 'used') $text = '❌ این کد قبلاً استفاده شده است.';
        elseif($err === 'disabled') $text = '❌ این کد غیرفعال شده است.';
        elseif($err === 'wallet_add_failed') $text = '❌ کد معتبر است، اما شارژ حساب انجام نشد. کد باطل نشد؛ چند لحظه بعد دوباره امتحان کنید یا به پشتیبانی اطلاع دهید.';
        else $text = '❌ این کد هدیه درست نیست یا دیگه فعال نیست.';
        bot('sendMessage', ['chat_id'=>$chatID, 'text'=>$text, 'parse_mode'=>'HTML', 'reply_markup'=>function_exists('bot_home_build_reply_keyboard') ? bot_home_build_reply_keyboard(false) : $Button_Home]);
        return true;
    }

    return false;
}
}
