<?php
// Advanced anti-fraud guard for referral and forced-join abuse.
// Goals:
// - Referral is recorded as pending on /start ref.
// - Referral is counted/rewarded only after the invited user completes mandatory join locks.
// - Suspicious cases are logged for admin review without spamming the main admin chat.

if(!function_exists('bot_fraud_settings_file')){
    function bot_fraud_settings_file(){ return 'lib/kodam/data-fraud.json'; }
}

if(!function_exists('bot_fraud_default_settings')){
    function bot_fraud_default_settings(){
        return [
            'enabled' => '✅فعال',
            'referral_require_forced_join' => '✅فعال',
            'strict_no_forced_join_no_reward' => '✅فعال',
            'notify_referrer_after_verified' => '✅فعال',
            'log_referral_start' => '✅فعال',
            'log_forced_join_leave' => '✅فعال',
            'min_verify_seconds' => 0,
            'pending_expire_days' => 14,
        ];
    }
}

if(!function_exists('bot_fraud_settings')){
    function bot_fraud_settings(){
        $s = function_exists('bot_data_get_json') ? bot_data_get_json(bot_fraud_settings_file(), []) : [];
        if(!is_array($s)) $s = [];
        $s = array_merge(bot_fraud_default_settings(), $s);
        $s['min_verify_seconds'] = max(0, (int)($s['min_verify_seconds'] ?? 0));
        $s['pending_expire_days'] = max(1, (int)($s['pending_expire_days'] ?? 14));
        return $s;
    }
}

if(!function_exists('bot_fraud_save_settings')){
    function bot_fraud_save_settings(array $settings){
        $old = bot_fraud_settings();
        $settings = array_merge($old, $settings);
        if(function_exists('bot_data_put_json')) return bot_data_put_json(bot_fraud_settings_file(), $settings);
        $dir = dirname(bot_fraud_settings_file()); if($dir && !is_dir($dir)) @mkdir($dir, 0775, true);
        return @file_put_contents(bot_fraud_settings_file(), json_encode($settings, JSON_UNESCAPED_UNICODE|JSON_PRETTY_PRINT), LOCK_EX) !== false;
    }
}

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

if(!function_exists('bot_fraud_install_schema')){
    function bot_fraud_install_schema(){
        $pdo = bot_fraud_pdo();
        if(!$pdo) return false;
        try{
            $pdo->exec("CREATE TABLE IF NOT EXISTS bot_fraud_events (
                id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
                user_id VARCHAR(32) NULL,
                referrer_id VARCHAR(32) NULL,
                event_type VARCHAR(60) NOT NULL,
                severity VARCHAR(20) NOT NULL DEFAULT 'info',
                message TEXT NULL,
                data_json LONGTEXT NULL,
                created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
                KEY idx_user (user_id),
                KEY idx_referrer (referrer_id),
                KEY idx_event_type (event_type),
                KEY idx_severity (severity),
                KEY idx_created (created_at)
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci");
            return true;
        }catch(Throwable $e){ error_log('BOT fraud schema failed: '.$e->getMessage()); return false; }
    }
}

if(!function_exists('bot_fraud_json')){
    function bot_fraud_json(array $data){ return function_exists('bot_json_encode') ? bot_json_encode($data) : json_encode($data, JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES); }
}

if(!function_exists('bot_fraud_log')){
    function bot_fraud_log($type, $userId=null, $referrerId=null, $severity='info', $message='', array $data=[]){
        $settings = bot_fraud_settings();
        if((string)($settings['enabled'] ?? '✅فعال') !== '✅فعال') return false;
        $userId = $userId === null ? null : preg_replace('/[^0-9]/', '', (string)$userId);
        $referrerId = $referrerId === null ? null : preg_replace('/[^0-9]/', '', (string)$referrerId);
        $severity = in_array((string)$severity, ['info','warning','danger'], true) ? (string)$severity : 'info';
        $ok = false;
        $pdo = bot_fraud_pdo();
        if($pdo && bot_fraud_install_schema()){
            try{
                $st = $pdo->prepare('INSERT INTO bot_fraud_events (user_id, referrer_id, event_type, severity, message, data_json) VALUES (?,?,?,?,?,?)');
                $ok = $st->execute([$userId ?: null, $referrerId ?: null, (string)$type, $severity, (string)$message, bot_fraud_json($data)]);
            }catch(Throwable $e){ error_log('BOT fraud log failed: '.$e->getMessage()); }
        }
        if(!is_dir('cache')) @mkdir('cache',0755,true);
        @file_put_contents('cache/fraud_events.log', date('c').' | '.$severity.' | '.$type.' | user='.$userId.' | ref='.$referrerId.' | '.$message.' | '.bot_fraud_json($data)."\n", FILE_APPEND);
        return $ok;
    }
}

if(!function_exists('bot_fraud_forced_join_channels')){
    function bot_fraud_forced_join_channels(){
        $channels = [];
        $add = function($value) use (&$channels, &$add){
            if(is_array($value)){ foreach($value as $v) $add($v); return; }
            $v = trim((string)$value);
            if($v === '') return;
            if(function_exists('normalize_bale_channel_username')){
                $norm = normalize_bale_channel_username($v);
                if($norm !== '') $v = $norm;
            }
            if($v !== '') $channels[] = $v;
        };
        if(function_exists('bale_forced_join_channels_active')) $add(bale_forced_join_channels_active());
        if(isset($GLOBALS['forcedJoinChannels']) && is_array($GLOBALS['forcedJoinChannels'])) $add($GLOBALS['forcedJoinChannels']);
        if(isset($GLOBALS['channel'])) $add($GLOBALS['channel']);
        if(isset($GLOBALS['channel2'])) $add($GLOBALS['channel2']);
        foreach(['lib/kodam/channel.txt','lib/kodam/channel2.txt'] as $p){
            $v = function_exists('bot_data_get_text') ? trim((string)bot_data_get_text($p, '')) : (is_file($p) ? trim((string)file_get_contents($p)) : '');
            $add($v);
        }
        $seen = [];
        $out = [];
        foreach($channels as $ch){
            $key = function_exists('bale_forced_join_channel_key') ? bale_forced_join_channel_key($ch) : strtolower($ch);
            if($key === '') $key = strtolower($ch);
            if(isset($seen[$key])) continue;
            $seen[$key] = true;
            $out[] = $ch;
        }
        return $out;
    }
}

if(!function_exists('bot_fraud_missing_forced_join_channels')){
    function bot_fraud_missing_forced_join_channels($userId, $force=true){
        $channels = bot_fraud_forced_join_channels();
        if(!$channels) return [];
        if(function_exists('bot_forced_join_missing_channels')) return bot_forced_join_missing_channels($channels, $userId, (bool)$force);
        $missing = [];
        foreach($channels as $ch){
            $status = function_exists('bale_get_channel_member_status_cached') ? bale_get_channel_member_status_cached($ch, $userId, null, (bool)$force) : null;
            if(!function_exists('bale_is_member_status') || !bale_is_member_status($status)) $missing[] = $ch;
        }
        return array_values(array_unique($missing));
    }
}

if(!function_exists('bot_fraud_referral_notice')){
    function bot_fraud_referral_notice(){
        $channels = bot_fraud_forced_join_channels();
        $count = count($channels);
        $line = $count > 0
            ? "🔐 برای اینکه دعوت شما حساب شود، زیرمجموعه باید حتماً در {$count} چنل قفل‌شده عضو شود و دکمه «✅ عضو شدم / بررسی مجدد» را بزند."
            : "🔐 ضدتقلب رفرال فعال است؛ ادمین باید قفل عضویت اجباری را تنظیم کند تا دعوت‌ها امن و قابل پاداش شوند.";
        return "

⚠️ قانون ضدتقلب رفرال
{$line}
صرفاً استارت‌زدن ربات با اکانت فیک، زیرمجموعه محسوب نمی‌شود و هیچ پاداشی نمی‌گیرد.";
    }
}

if(!function_exists('bot_fraud_has_active_forced_join')){
    function bot_fraud_has_active_forced_join(){
        return count(bot_fraud_forced_join_channels()) > 0;
    }
}

if(!function_exists('bot_fraud_should_defer_start_gift')){
    function bot_fraud_should_defer_start_gift($userId=null){
        $settings = bot_fraud_settings();
        if((string)($settings['enabled'] ?? '✅فعال') !== '✅فعال') return false;
        if((string)($settings['strict_no_forced_join_no_reward'] ?? '✅فعال') !== '✅فعال') return false;
        return bot_fraud_has_active_forced_join();
    }
}

if(!function_exists('bot_fraud_prepare_new_user_for_start_gift')){
    function bot_fraud_prepare_new_user_for_start_gift(array $user, $userId=null){
        if(!bot_fraud_should_defer_start_gift($userId)) return $user;
        if(!empty($user['start_gift_awarded']) || !empty($user['pending_start_gift'])) return $user;
        $amount = max(0, (int)($user['Points'] ?? (function_exists('bot_join_gift_amount') ? bot_join_gift_amount() : 0)));
        if($amount > 0){
            $user['pending_start_gift'] = $amount;
            $user['start_gift_awarded'] = 0;
            $user['start_gift_pending_reason'] = 'forced_join_required';
            $user['start_gift_pending_at'] = time();
            $user['Points'] = '0';
        }
        return $user;
    }
}

if(!function_exists('bot_fraud_award_pending_start_gift')){
    function bot_fraud_award_pending_start_gift($userId, $force=true){
        $uid = preg_replace('/[^0-9]/', '', (string)$userId);
        if($uid === '') return ['ok'=>false,'reason'=>'bad_user'];
        $user = function_exists('bot_data_get_json') ? bot_data_get_json("melat/$uid.json", []) : [];
        if(!is_array($user)) $user = [];
        $pending = max(0, (int)($user['pending_start_gift'] ?? 0));
        if($pending <= 0 || !empty($user['start_gift_awarded'])) return ['ok'=>true,'reason'=>'nothing_pending'];
        $missing = bot_fraud_missing_forced_join_channels($uid, (bool)$force);
        if($missing){
            bot_fraud_log('start_gift_waiting_for_forced_join', $uid, null, 'info', 'هدیه استارت تا تکمیل قفل جوین در انتظار است.', ['missing_channels'=>$missing]);
            return ['ok'=>false,'reason'=>'missing_forced_join','missing'=>$missing];
        }
        $before = (int)($user['Points'] ?? 0);
        $after = $before + $pending;
        $user['Points'] = (string)$after;
        $user['start_gift_awarded'] = time();
        $user['pending_start_gift'] = 0;
        $user['wallet_log'][] = ['time'=>time(),'reason'=>'start_gift_after_forced_join','delta'=>$pending,'before'=>$before,'after'=>$after];
        if(function_exists('saveJson')) saveJson("melat/$uid.json", $user);
        elseif(function_exists('bot_data_put_json')) bot_data_put_json("melat/$uid.json", $user);
        bot_fraud_log('start_gift_awarded_after_forced_join', $uid, null, 'info', 'هدیه استارت بعد از تکمیل قفل جوین داده شد.', ['amount'=>$pending,'before'=>$before,'after'=>$after]);
        return ['ok'=>true,'awarded'=>$pending,'before'=>$before,'after'=>$after];
    }
}

if(!function_exists('bot_fraud_guard_forced_join_leave')){
    function bot_fraud_guard_forced_join_leave($userId, array $missingChannels){
        if(!$missingChannels) return false;
        $settings = bot_fraud_settings();
        if((string)($settings['log_forced_join_leave'] ?? '✅فعال') !== '✅فعال') return false;
        $uid = preg_replace('/[^0-9]/', '', (string)$userId);
        if($uid === '') return false;
        $u = function_exists('bot_data_get_json') ? bot_data_get_json("melat/$uid.json", []) : [];
        if(!is_array($u) || empty($u['ref_signup_rewarded'])) return false;
        $last = (int)($u['ref_forced_leave_logged_at'] ?? 0);
        if($last > 0 && time() - $last < 3600) return false;
        $u['ref_forced_leave_logged_at'] = time();
        $u['ref_forced_leave_count'] = (int)($u['ref_forced_leave_count'] ?? 0) + 1;
        if(function_exists('saveJson')) saveJson("melat/$uid.json", $u);
        elseif(function_exists('bot_data_put_json')) bot_data_put_json("melat/$uid.json", $u);
        return bot_fraud_log('forced_join_left_after_referral_reward', $uid, $u['sub'] ?? ($u['referrer_id'] ?? null), 'warning', 'کاربر دعوت‌شده بعد از تأیید رفرال از قفل جوین خارج شده یا عضویتش قابل تأیید نیست.', ['missing_channels'=>array_values($missingChannels)]);
    }
}

if(!function_exists('bot_fraud_admin_summary')){
    function bot_fraud_admin_summary($limit=20){
        bot_fraud_install_schema();
        $pdo = bot_fraud_pdo();
        $rows = [];
        $total = $warn = $danger = 0;
        if($pdo){
            try{
                $total = (int)$pdo->query('SELECT COUNT(*) FROM bot_fraud_events')->fetchColumn();
                $warn = (int)$pdo->query("SELECT COUNT(*) FROM bot_fraud_events WHERE severity='warning'")->fetchColumn();
                $danger = (int)$pdo->query("SELECT COUNT(*) FROM bot_fraud_events WHERE severity='danger'")->fetchColumn();
                $st = $pdo->query('SELECT * FROM bot_fraud_events ORDER BY id DESC LIMIT '.(int)$limit);
                foreach($st as $r) $rows[] = $r;
            }catch(Throwable $e){}
        }
        return ['total'=>$total,'warning'=>$warn,'danger'=>$danger,'rows'=>$rows];
    }
}
