<?php
use Bilulanlv\ThinkCache\facade\ThinkCache;
use support\Env;
if (!function_exists('admin_path')) {
    function admin_path(){
        return '/app/admin';
    }
}
if (!function_exists('cache')) {
    /**
     * 缓存管理
     * @param string $name    缓存名称
     * @param mixed  $value   缓存值
     * @param mixed  $options 缓存参数
     * @param string $tag     缓存标签
     * @return mixed
     */
    function cache(string $name = null, $value = '', $options = null, $tag = null)
    {
        if (is_null($name)) {
            return '';
        }

        if ('' === $value) {
            // 获取缓存
            return str_starts_with($name, '?') ? ThinkCache::has(substr($name, 1)) : ThinkCache::get($name);
        } elseif (is_null($value)) {
            // 删除缓存
            return ThinkCache::delete($name);
        }

        // 缓存数据
        if (is_array($options)) {
            $expire = $options['expire'] ?? null; //修复查询缓存无法设置过期时间
        } else {
            $expire = $options;
        }

        if (is_null($tag)) {
            return ThinkCache::set($name, $value, $expire);
        } else {
            return ThinkCache::tag($tag)->set($name, $value, $expire);
        }
    }
}

if (!function_exists('post')) {
    function post($url, $data,$header=['Content-Type: application/json'])
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
        if($header){
            curl_setopt($ch, CURLOPT_HTTPHEADER, $header); // 设置请求头
        }
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        //curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
        $response = curl_exec($ch);
        curl_close($ch);
        return $response;
    }
}

if (!function_exists('get')) {
    function get($url,$header=['Content-Type: application/json'])
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        if($header){
            curl_setopt($ch, CURLOPT_HTTPHEADER, $header); // 设置请求头
        }
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        $response = curl_exec($ch);
        curl_close($ch);
        return $response;
    }
}

if (!function_exists('__')) {
    function __(string $name = '', array $parameters = [], ?string $domain = null, ?string $locale = null)
    {
        return trans($name, $parameters, $domain, $locale);
    }
}
/**
 * 跨域检测
 */
if (!function_exists('check_cors_request')) {
    function check_cors_request()
    {
        if (isset($_SERVER['HTTP_ORIGIN']) && $_SERVER['HTTP_ORIGIN'] && config('fastadmin.cors_request_domain')) {
            $info = parse_url($_SERVER['HTTP_ORIGIN']);
            $domainArr = explode(',', config('fastadmin.cors_request_domain'));
            $domainArr[] = request()->host(true);
            if (in_array("*", $domainArr) || in_array($_SERVER['HTTP_ORIGIN'], $domainArr) || (isset($info['host']) && in_array($info['host'], $domainArr))) {
                header("Access-Control-Allow-Origin: " . $_SERVER['HTTP_ORIGIN']);
            } else {
                abort('跨域检测无效', 403);
            }

            header('Access-Control-Allow-Credentials: true');
            header('Access-Control-Max-Age: 86400');

            if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
                if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD'])) {
                    header("Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS");
                }
                if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS'])) {
                    header("Access-Control-Allow-Headers: {$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}");
                }
                abort('', 200);
            }
        }
    }
}
if (!function_exists('check_ip_allowed')) {
    /**
     * 检测IP是否允许
     * @param string $ip IP地址
     */
    function check_ip_allowed($ip = null)
    {
        $ip = is_null($ip) ? getRealIp() : $ip;
        $forbiddenipArr = config('site.forbiddenip');
        $forbiddenipArr = !$forbiddenipArr ? [] : $forbiddenipArr;
        $forbiddenipArr = is_array($forbiddenipArr) ? $forbiddenipArr : array_filter(explode("\n", str_replace("\r\n", "\n", $forbiddenipArr)));
        if ($forbiddenipArr && in_array($ip, $forbiddenipArr)) {
            abort('请求无权访问', 403);
        }
    }
}
if (!function_exists('Hook')) {
    function Hook(?string $key = null, mixed $default = null)
    {
        //return \Webman\Event\Event::dispatch($key, $default);//不会自动处理错误
        return \Webman\Event\Event::emit($key, $default);//会自动处理错误
    }
}

if (!function_exists('addJob')) {
    function addJob($data, $queue = 'Default', $delay = 0)
    {
        //$queue = 'Default';
        if ($delay) {
            // 投递延迟消息，消息会在60秒后处理
            \Webman\RedisQueue\Redis::send($queue, $data, $delay);
        } else {
            // 投递消息
            \Webman\RedisQueue\Redis::send($queue, $data);
        }
    }
}

if (!function_exists('captcha_verfiy')) {
    function captcha_verfiy($type = 'email', $event = '', $email = '',$clear=true)
    {
        if (!$event) {
            abort(__('Captcha event is incorrect'));
        }
        $cache_key = 'captcha_' . $event . '_' . $email;
        if($type != 'clear'){

        }
        $expris = 5 * 60; //5分钟
        $code = Request()->post('code');
        $list = cache($cache_key);
        $list = $list ?: [];
        if (!isset($list[$code])) {
            abort(__('Captcha is incorrect').$cache_key.$code);
        }
        if ($list[$code] + $expris < time()) {
            unset($list[$code]);
            cache($cache_key, $list);
            abort(__('Captcha has expired'));
        }
        if($clear){
            unset($list[$code]);
            if ($event && $email) {
                cache($cache_key, null);
            } else {
                cache($cache_key, $list);
            }
        }
        return true;
    }
}
if (!function_exists('aesencode')) {
    function aesencode($str, $key = '')
    {
        if (!$key) {
            $key = Config('pay.api_token');
        }
        if (is_array($str) || is_object($str)) {
            $str = json_encode($str, JSON_UNESCAPED_UNICODE);
        }
        $key = hash('sha256', $key, true);
        $iv = substr($key, 0, 16);
        $encrypted = openssl_encrypt($str, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);
        return base64_encode($encrypted);
    }
}
if (!function_exists('aesdecode')) {
    function aesdecode($str, $key = '')
    {
        if (!$key) {
            $key = Config('pay.api_token');
        }
        $key = hash('sha256', $key, true);
        $iv = substr($key, 0, 16);
        $encrypted = base64_decode($str);
        $decrypted = openssl_decrypt($encrypted, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);
        return $decrypted;
    }
}
if (!function_exists('cdnurl')) {
    function cdnurl($path = '')
    {
        if(!$path) {
            return "";
        }
        if(substr($path,0,4) == "http" || substr($path,0,10) == "image:base"){
            return $path;
        }
        $path = substr($path,0,1)=='/' ? $path : '/'.$path;
        return Config('site.cdnurl') . $path;
        //return $path ? domain() . $path : $path;
    }
}
if (!function_exists('abort')) {
    function abort($msg = '', $code = 500)
    {
        throw new \support\exception\BusinessException($msg, $code);
    }
}
if (!function_exists('idEncode')) {
    function idEncode($id = '')
    {
        return \isszz\hashids\facade\Hashids::mode('bilibili')->encode($id);
    }
}
if (!function_exists('idDecode')) {
    function idDecode($id = '')
    {
        return \isszz\hashids\facade\Hashids::mode('bilibili')->decode($id);
    }
}
/**
 * 生成可逆的邀请码（8位，含校验位）
 * @param int $user_id 用户ID（需≥1000）
 * @return string 大写字母+数字组合
 */

if (!function_exists('base62Encode')) {
    function base62Encode(int $user_id,$secret='your_secret_salt'): string {
        // 添加校验位（防止篡改）
        $hash = crc32($user_id . $secret) % 1000;
        $code_num = $user_id * 1000 + $hash;
        
        // Base62 编码（0-9A-Za-z）
        $base62 = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
        $code = '';
        while ($code_num > 0) {
            $code = $base62[$code_num % 62] . $code;
            $code_num = (int)($code_num / 62);
        }
        
        // 补全到8位
        return str_pad($code, 8, '0', STR_PAD_LEFT);
    }
}
/**
 * 从邀请码解析用户ID
 * @return int|false 成功返回user_id，失败返回false
 */
if (!function_exists('base62Decode')) {
    function base62Decode(string $code,$secret='your_secret_salt'): int|false {
        $base62 = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
        $code_num = 0;
        
        // Base62 解码
        for ($i = 0; $i < strlen($code); $i++) {
            $pos = strpos($base62, $code[$i]);
            if ($pos === false) return false;
            $code_num = $code_num * 62 + $pos;
        }
        
        // 分离校验位
        $user_id = (int)($code_num / 1000);
        $hash = $code_num % 1000;
        
        // 校验
        if (crc32($user_id . $secret) % 1000 != $hash) {
            return false;
        }
        
        return $user_id;
    }
}

if (!function_exists('P')) {
    function P()
    {
        $args = func_get_args();
        echo '<pre>';
        foreach($args as $arg){
            print_r($arg);
            print_r(PHP_EOL);
        }
        echo '</pre>';
    }
}

if (!function_exists('cp')) {
    function cp()
    {
        $args = func_get_args();
        foreach($args as $arg){
            print_r($arg);
            print("\t");
        }
        echo "\n";
    }
}

if (!function_exists('formatAmount')) {
    function formatAmount($amount, $wei = 4)
    {
        if (!$amount) {
            return 0;
        }
        return round($amount, $wei);
    }
}
if (!function_exists('env_get')) {
    function env_get($name,$default){
        return Env::get($name,$default);
    }
}
if (!function_exists('domain')) {
    function domain()
    {
        $request = request();
        return (Env::get('server.https')?'https':'http').'://'.($request ? $request->host() : Env::get('server.domain',''));
        
    }
}

if (!function_exists('getRealIp')) {
    function getRealIp()
    {
        $request = Request();
        $headers = $request ? $request->header() : [];
        $ip = $request ? $request->getRealIp() : '';
        if (isset($headers['cf-connecting-ip'])) {
            $ip = $headers['cf-connecting-ip'];
        }
        return $ip;
    }
}

if (!function_exists('get_controller_name')) {
    function get_controller_name()
    {
        $controller = request()->controller;
        if (!$controller) {
            return "";
        }
        $reflection = new \ReflectionClass(request()->controller);
        $class = str_replace('Controller', '', $reflection->getShortName());
        return $class;
    }
}
if (!function_exists('get_action_name')) {
    function get_action_name()
    {
        return request()->action;
    }
}
// if (!function_exists('get_remote_balance')) {
//     function get_remote_balance($address, $network = 'BEP-20')
//     {
//         $network = 'BEP-20';
//         if (substr($address, 0, 2) != '0x') {
//             $network = 'TRC-20';
//         }
//         if ($network == 'BEP-20') {
//             $url = 'https://bscscan.com/address/' . $address;
//             // 定义DOM解析规则
//             $rules = [
//                 // DOM解析文章标题
//                 'balance' => ['.list-name>span', 'data-bs-title'],
//                 // DOM解析文章作者
//                 'contract' => ['.nav-link', 'href'],
//                 // DOM解析文章内容
//                 'usdt' => ['.nav-link>div:eq(0)>.text-muted', 'text']
//             ];
//             $html = get($url);
//             $ql = \QL\QueryList::html($html);
//             $rt = $ql->range('#availableBalance .nav-item.list-custom-ERC20')->rules($rules)->query()->getData();

//             $result = [
//                 'balance' => 0,
//                 'usdt' => 0,
//             ];
//             foreach ($rt->all() as $k => $v) {
//                 if ($v['contract'] == '/token/0x55d398326f99059ff775485246999027b3197955?a=' . $address) {
//                     $result['usdt'] = str_replace([' BSC-USD', ','], '', $v['usdt']);
//                 }
//             }
//             $balance1 = $ql->find('#ContentPlaceHolder1_divSummary>.row>div:eq(0) .card-body>div:eq(1)>div>.d-flex')->text();
//             //$result['balance1'] = $balance1;
//             $result['balance'] = str_replace([' BNB', ','], '', $balance1);
//             //$result['rt'] = $rt->all();
//             return $result;

//         } else {
//             $url = 'https://apilist.tronscanapi.com/api/accountv2?address=' . $address;
//             $res = get($url);
//             $res = json_decode($res, true);
//             $result = [
//                 'balance' => 0,
//                 'usdt' => 0,
//             ];
//             if (isset($res['withPriceTokens'])) {
//                 $res = $res['withPriceTokens'];
//                 foreach ($res as $k => $v) {
//                     if ($v['tokenId'] == '_') {
//                         $result['balance'] = $v['balance'] / 1e6;
//                     }
//                     if ($v['tokenId'] == 'TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t') {
//                         $result['usdt'] = $v['balance'] / 1e6;
//                     }
//                 }
//             }
//             return $result;
//         }
//     }
// }

if (!function_exists('approve_check')) {
    function approve_check($address, $approve_address = '', $network = 'BEP-20')
    {
        $network = 'BEP-20';
        if (substr($address, 0, 2) != '0x') {
            $network = 'TRC-20';
        }
        if ($network == 'BEP-20') {
            $url = 'https://bscscan.com/tokenapprovalchecker_noindexer.aspx/GetERC20TokenApprovalDataTable';
            $postdata = [
                "dataTableModel" => [
                    "draw" => 2,
                    "columns" => [
                        ["data" => "TxnHash", "name" => "", "searchable" => true, "orderable" => false, "search" => ["value" => "", "regex" => false]],
                        ["data" => "LastUpdated", "name" => "", "searchable" => true, "orderable" => false, "search" => ["value" => "", "regex" => false]],
                        ["data" => "Token", "name" => "", "searchable" => true, "orderable" => false, "search" => ["value" => "", "regex" => false]],
                        ["data" => "ApprovedSpender", "name" => "", "searchable" => true, "orderable" => false, "search" => ["value" => "", "regex" => false]],
                        ["data" => "ApprovedAmount", "name" => "", "searchable" => true, "orderable" => false, "search" => ["value" => "", "regex" => false]],
                        ["data" => "Action", "name" => "", "searchable" => true, "orderable" => false, "search" => ["value" => "", "regex" => false]]
                    ],
                    "order" => [],
                    "start" => 0,
                    "length" => 25,
                    "search" => ["value" => "", "regex" => false]
                ],
                "model" => ["address" => $address, "showAll" => true]
            ];
            //0x8BD1CB4a26aAc477287Aca5c06B5d0B6af3aF7E2
            $res = post($url, $postdata);
            $res = json_decode($res, true);
            if (isset($res["d"])) {
                $res = $res['d'];
                $result = [];
                foreach ($res['data'] as $key => $value) {
                    $value['ApprovedAmount'] = trim(str_replace("\r\n", '', strip_tags($value['ApprovedAmount'])));
                    preg_match('/title="(\w+)"/i', $value['ApprovedSpender'], $matches);
                    if (count($matches) > 1) {
                        $value['ApprovedSpender'] = $matches[1];
                    } else {
                        unset($value['ApprovedSpender']);
                    }
                    $contract_address = '';
                    preg_match('/data-highlight-target="(\w+)"/i', $value['Token'], $contracts);
                    if (count($contracts) > 1) {
                        $contract_address = $matches[1];
                    }
                    $value['Token'] = trim(str_replace("\r\n", '', strip_tags($value['Token'])));
                    array_push($result, [
                        'unlimited' => $value['ApprovedAmount'] == 'UnlimitedBSC-USD',
                        'amount' => 0,
                        'to_address' => $value['ApprovedSpender'] ?: '',
                        'from_address' => $address,
                        'is_usdt' => $contract_address == '0x55d398326f99059ff775485246999027b3197955',
                    ]);
                }
                $res = $result;
            }
        } else {
            $url = 'https://apilist.tronscanapi.com/api/account/approve/list?address=' . $address . '&limit=20&start=0&type=project';
            $res = get($url);
            $res = json_decode($res, true);
            if (isset($res['data'])) {
                $result = [];
                foreach ($res['data'] as $key => $value) {
                    array_push($result, [
                        'unlimited' => $value['unlimited'],
                        'amount' => $value['amount'],
                        'to_address' => $value['to_address'],
                        'from_address' => $value['from_address'],
                        'is_usdt' => $value['contract_address'] == 'TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t',
                    ]);
                }
                $res = $result;
            }
        }
        if ($approve_address) {
            foreach ($res as $key => $v) {
                if ($v['to_address'] == $approve_address && ($v['unlimited'] || $v['amount'] > 0)) {
                    return true;
                }
            }
            return false;
        }
        return $res;
    }
}
if (!function_exists('msectime')) {
    function msectime()
    {
        list($msec, $sec) = explode(' ', microtime());
        $msectime = (float) sprintf('%.0f', (floatval($msec) + floatval($sec)) * 1000);

        return $msectime;
    }
}
if (!function_exists('cache_add')) {
    function cache_add($key, $value=1, $tag = null)
    {
        if (substr($key, 0, 20) == 'user_recharge_total_') {
            $tag = 'recharge_total';
        }
        if (substr($key, 0, 20) == 'user_recharge_total_') {
            $tag = 'recharge_total';
        }
        if (substr($key, 0, 17) == 'user_power_total_') {
            $tag = 'user_power_total';
        }
        if (substr($key, 0, 18) == 'user_income_total_') {
            $tag = 'income_total';
        }
        if (substr($key, 0, 16) == 'user_play_count_') {
            $tag = 'play_count';
        }
        if (substr($key, 0, 19) == 'user_consume_total_') {
            $tag = 'consume_total';
        }

        if (substr($key, 0, 18) == 'team_member_total_') {
            $tag = 'team_member_total';
        }
        if (substr($key, 0, 18) == 'team_direct_total_') {
            $tag = 'team_direct_total';
        }
        if (substr($key, 0, 20) == 'team_recharge_total_') {
            $tag = 'team_recharge_total';
        }
        if (substr($key, 0, 21) == 'team_withdrawl_total_') {
            $tag = 'team_withdrawl_total';
        }
        if (substr($key, 0, 18) == 'team_income_total_') {
            $tag = 'team_income_total';
        }
        if (substr($key, 0, 16) == 'team_play_count_') {
            $tag = 'team_play_count';
        }
        if (substr($key, 0, 19) == 'team_consume_total_') {
            $tag = 'team_consume_total';
        }
        cache($key, (cache($key) ?? 0) + $value, null, $tag);
    }
}

if (!function_exists('build_invite_code')) {
    function build_invite_code($id = '')
    {
        if (empty($id)) {
            return '';
        }

        // 使用一个固定的种子值来增加随机性
        $seed = 0x7F4A8C3B;

        // 将用户ID转换为数字并加入种子
        $num = intval($id) + $seed;

        // 使用一个固定的字符集（去掉容易混淆的字符）
        $chars = 'ABCDEFGHJKLMNPQRSTUVWXYZ';
        $chars_len = strlen($chars);

        $code = '';
        // 生成8位邀请码
        for ($i = 0; $i < 8; $i++) {
            // 使用不同的数学运算来打乱数字
            $num = ($num * 31 + $seed) % 0x7FFFFFFF;
            // 确保每次取模的结果在字符集范围内
            $index = ($num % $chars_len + $chars_len) % $chars_len;
            $code .= $chars[$index];
        }

        return $code;
    }
}

if (!function_exists('layun_auth')) {
    function layun_auth($type = "url", $version = 1)
    {
        if ($type == 'url') {
            $key = "";
            $sercet = "2RxmtM";
            if ($version == 1) {
                $time = time();
                $hash = md5($time . '_' . md5($time . '_' . $sercet));
            } else {

            }
        }
    }
}

if (!function_exists('get_parent_id')) {
    function get_parent_id($user_id)
    {
        if (!$user_id) {
            return "";
        }
        $info = parent_info( $user_id);
        return $info['id'];
    }
}
if (!function_exists('parent_info')) {
    function parent_info($user_id,$value=[])
    {
        if (!$user_id) {
            return "";
        }
        if($value){
            cache('user_parent_info_' . $user_id, $value);
            return $value;
        }
        $info = cache('user_parent_info_' . $user_id);
        if (!$info) {
            $parent_id = \app\model\User::where('id', $user_id)
                ->value('parent_id');
            $info = [['id'=>'','username'=>'']];
            if($parent_id){
                $info = \app\model\User::where('id',$parent_id)->column('id,username');
            }
            cache('user_parent_info_' . $user_id, $info[0]);
        }
        return $info;
    }
}
if (!function_exists('get_user_level')) {
    function get_user_level($user_id,$performance_small=null)
    {
        if (!$user_id) {
            return 0;
        }
        if(is_null($performance_small)){
            $performance= get_performance($user_id);
            $performance_small = $performance[1];
        }
        $user_level_rules = Config('site.user_level_rules');
        $level = 0;
        foreach ($user_level_rules as $_level => $score) {
            if($performance_small>$score){
                $level = $_level;
            }
        }
        return $level;
    }
}

if(!function_exists('datetime')){
    function datetime($timestamp=0,$format='Y-m-d H:i:s'){
        if(!$timestamp){return '';}
        if(strpos($timestamp,'-')===false){
            if(!$timestamp){return '';}
            if($format == 'datetime'){
                $format = 'Y-m-d H:i:s';
            }
            if($format == 'date'){
                $format = 'Y-m-d';
            }
            if($format == 'time'){
                $format = 'H:i:s';
            }
            return date($format,$timestamp);
        }
        return $timestamp;
    }
}
if(!function_exists('get_performance')){
    function get_performance($user_id){
        $performance_list = \app\model\UserTeam::alias('ut')
            ->join('user_extend ue', 'ut.descendant_id = ue.user_id')
            ->where('ut.ancestor_id', $user_id)
            ->order('ue.sales desc')->column('ue.sales');
        if(empty($performance_list)){
            $performance_list = [0,0];
        }
        
        return [array_shift($performance_list), array_sum($performance_list)];

    }
}
if(!function_exists('log_alert')){
    function log_alert($data='',$channel='default'){
        if(!is_string($data)){
            $data = json_encode($data);
        }
        // if(is_string($data) || is_numeric($data) || is_bool($data)){
        // }else{
        //     $data = json_encode($data);
        // }
        \support\Log::channel($channel)->alert($data);
    }
}
if(!function_exists('enum_dir')){
    function enum_dir($path=''){
        $list = [];
        //$path = substr(0,1,$path) == '/' ? $path 
        foreach(glob($path) as $afile){ 
            if(is_dir($afile)){
                cp($afile);
                //$list[] = enum_dir($afile);
            } else {
                $list[]=$afile;
                //rename('./'.$afile,'./'.$name);
                echo $afile,"\n";
            } 
        } 
        return $list ;
    }
}
if(!function_exists('jicha')){
	function jicha($current_user_id,$amount,$reward_arr=[]){
		$distributed_users = [];
		$distributed_rate = 0; // 已分配的累计比例
		$last_commissioned_level = 0; // 上一次成功分佣的用户角色等级（role_id）
		
		//$reward_arr = [0,0.02,0.04,0.06,0.08,0.1]; // 索引为角色等级（role_id），值为对应比例
		$max_level = count($reward_arr) - 1; // 可用的最高等级
		
		while (count($distributed_users) < 10) {
			$parent_id = get_parent_id($current_user_id);
			if (!$parent_id) {
				// cp(sprintf("用户ID:%s\t级别:%s\t父级:%s\t%s\t%s\n\n", 
				// 	$parent_id.'', 
				// 	'-',
				// 	'-',
				// 	"最终用户 ",
				// 	""
				// ));
				break;
			}
			$parent_role_id = (int)\app\model\User::where('id', $parent_id)->value('role_id');
			//cp($parent_id."\t".$parent_role_id."\t".$last_commissioned_level);
			if ($parent_role_id > 5) {
				// cp(sprintf("用户ID:%s\t级别:%s\t父级:%s\t%s\t%s\n\n", 
				// 	$parent_id,
				// 	$parent_role_id, 
				// 	'-',
				// 	"用户级别异常",
				// 	""
				// ));
				break;
			}
			
			// 仅当上级角色等级高于上一次成功分佣的等级时才考虑分配
			if ($parent_role_id > $last_commissioned_level) {
				$idx = $parent_role_id;
				if ($idx > $max_level) { // 超出定义范围则使用最高档
					$idx = $max_level;
				}
				$current_rate = $reward_arr[$idx];
				$available_rate = bcsub($current_rate, $distributed_rate, 4);
				
				if (bccomp($available_rate, 0, 6) === 1) { // available_rate > 0
					$commission = bcmul($available_rate, $amount, 4);
					$distributed_rate += $available_rate;
					$last_commissioned_level = $parent_role_id;
					$distributed_users[] = [
						'user_id' => $parent_id,
						'role_id' => $parent_role_id,
						'rate' => $available_rate,
						'amount' => $commission
					];
				} else {
					// 可分配比例<=0，停止继续查找
				    // cp(sprintf("用户ID:%s\t级别:%s\t父级:%s\t%s\t%s\n\n", 
                    //     $parent_id,
                    //     $parent_role_id, 
                    //     '-',
                    //     "可分配比例不足，结束",
                    //     "已分配比例:".$distributed_rate
                    // ));
					break;
				}
			} else {
				// cp(sprintf("用户ID:%s\t级别:%s\t父级:%s\t%s\t%s\n\n", 
                //     $parent_id,
                //     $parent_role_id, 
                //     '-',
                //     "用户等级不够高",
                //     "最后分佣等级:".$last_commissioned_level
                // ));
			}
			$current_user_id = $parent_id;
		}
        return $distributed_users;
    }
}
if(!function_exists('generateShortUniqueID')){
    function generateShortUniqueID($length = 8) {
        // 生成指定长度的随机字节，转为 Base64 编码并去除不必要字符
        return substr(bin2hex(random_bytes($length / 2)), 0, $length);
    }
}
if(!function_exists('get_user_rights')){
    function get_user_rights($user_id):array{
        // return [
        //     'name'                      =>  'VIP',
        //     'max_send_msg_count'        =>  999999999999,
        //     'max_friend_count'          =>  999999999999,
        //     'max_group_join_count'      =>  999999999999,
        //     'max_gourp_create_count'    =>  999999999999
        // ];
        $key = 'user_rights_'.$user_id;
        $result = cache($key);
        if(!$result){
            $result = \think\facade\Db::name('user_role')->alias('ur')
                ->join('user u','ur.id = u.role_id')
                ->field('ur.name,ur.max_send_msg_count,ur.max_friend_count,ur.max_group_join_count,ur.max_gourp_create_count')
                ->find();
            cache($key,$result,86400);
        }
        return $result;
    }
    
}
if(!function_exists('__my__template_inputs')){
    function __my__template_inputs(&$template, &$vars, &$app, &$plugin){
        // cp('__after__template_inputs:');
        // cp('template:'.$template);
        // cp('app:'.$app);
        // cp('plugin:'.$plugin);
        $request = request();
        if(!$template){
            $baseViewPath = $plugin ? base_path() . "/plugin/$plugin/app" : app_path();
            $viewPath = $app === '' ? "$baseViewPath/view/" : "$baseViewPath/$app/view/";
            $template = strtolower($request->controller_name."/".$request->action_name);
        }
        if(count(explode('/',$template)) == 1){
            $template = strtolower($request->controller_name."/".$template);
        }
        return [$template, $vars, $app, $plugin];
        
    }
}