<?php


namespace App\Http\Controllers\Api;


use App\Util;
use Illuminate\Support\Facades\Redis;
use App\Facade\TableName;
use App\Http\Controllers\Controller;
use App\Models\AccountsSource;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

class GameApiController extends Controller
{
    // 修改用户信息--【昵称，和头像】
    public function updateUserInfo(Request $request)
    {
        $FaceID = $request->FaceID ?: '';
        $NickName = $request->NickName ?: '';
        $UserID = $request->UserID ?: '';

        if (empty($UserID)) {
            return apiReturnFail(__('messages.api.game_api.user_info_lost'));
        }
        $data = compact('FaceID', 'NickName');
        $data = array_filter($data);


        if (!empty($data)) {
            DB::table(TableName::QPAccountsDB() . 'AccountsInfo')
                ->where('UserID', $UserID)
                ->update($data);
        }
        return apiReturnSuc();
    }

    // 用户来源
    public function UserSource(Request $request)
    {
        $UserID = $request->input('UserID');
        $Source = $request->input('Source');
        $RequestDynamicPass = $request->input('DynamicPass');
        // 验证用户信息
        $DynamicPass = DB::table(TableName::QPAccountsDB() . 'AccountsInfo')
            ->where('UserID', $UserID)
            ->value('DynamicPass');
        if ($DynamicPass != $RequestDynamicPass || empty($DynamicPass)) return apiReturnFail(__('messages.api.game_api.player_info_inconsistent'));


        (new AccountsSource())->notExistsInsert($UserID, $Source);

        return apiReturnSuc();
    }
    public function billBoard(Request $request){
        return $this->billBoard2($request);
        $UserID = $request->input('UserID');
        $cachekey="Bill_board";
        $myrank=10000;
        if(Redis::exists($cachekey)){
            $boards=json_decode(Redis::get($cachekey),true);
        }
        $datekey=date("Ymd");
        $datekey2=date("Ymd",time()-86400);
        if(!isset($boards)||Redis::ttl($cachekey)<305){
            $boards=[];

            $list = DB::connection('read')->table('QPAccountsDB.dbo.AccountsInfo as ai')
                ->leftJoin('QPRecordDB.dbo.RecordUserDataStatisticsNew as gi', 'ai.UserID', '=', 'gi.UserID')
                ->whereIn('gi.DateID',[$datekey,$datekey2])
                ->orderBy('gi.WinScore','desc')
                ->limit(900)
                ->select(['ai.UserID','gi.WinScore as Score','ai.GameID','ai.NickName','ai.FaceID'])
                ->get()->toArray();


            foreach ($list as $key=>$value){
                $value=(array)$value;
                $value['FaceID']=intval($value['FaceID']);
                $value['Score']=floor($value['Score']/100)*100;
                $list[$key]=$value;

            }

            $all=Util::arraySort($list,'Score',SORT_DESC);
            foreach ($all as $key=>&$value){
                $value['rank']=$key+1;
            }
            $boards=$all;
            Redis::set($cachekey,json_encode($boards));
            //23:40以后冻结1小时
            if(intval(date("H"))==23&&intval(date("i"))>=40){
                Redis::expire($cachekey,3705);
            }else{
                Redis::expire($cachekey,1205);
            }

        }
        foreach ($boards as $value){
            if($value['UserID']==$UserID){
                $myrank=$value['rank'];
            }
        }
        return apiReturnSuc(['ret' =>['myData'=>['rank'=>$myrank],'rank'=>array_slice($boards,0,100)]]);
    }
    public function billBoard2(Request $request){
        $UserID = $request->input('UserID');
        $cachekey="Bill_boardd";
        $fakecachekey="Fake_Bill_boardd";
        $myrank=10000;

        // 检查是否存在真实用户排行榜数据缓存
        if(Redis::exists($cachekey)){
            $boards=json_decode(Redis::get($cachekey),true);
        }

        $datekey=date("Ymd");
        $datekey2=date("Ymd",time()-86400);

        // 获取真实用户排行榜数据
        if(!isset($boards)||Redis::ttl($cachekey)<205){
            $boards=[];

            $list = DB::connection('read')->table('QPAccountsDB.dbo.AccountsInfo as ai')
                ->leftJoin('QPRecordDB.dbo.RecordUserDataStatisticsNew as gi', 'ai.UserID', '=', 'gi.UserID')
                ->whereIn('gi.DateID',[$datekey,$datekey2])
                ->orderBy('gi.WinScore','desc')
                ->limit(900)
                ->select(['ai.UserID','gi.WinScore as Score','ai.GameID','ai.NickName','ai.FaceID'])
                ->get()->toArray();


            foreach ($list as $key=>$value){
                $value=(array)$value;
                $value['FaceID']=intval($value['FaceID']);
                $value['Score']=floor($value['Score']/100)*100;
                $list[$key]=$value;

            }

            $all=Util::arraySort($list,'Score',SORT_DESC);
            foreach ($all as $key=>&$value){
                $value['rank']=$key+1;
            }
            $boards=$all;
            Redis::set($cachekey,json_encode($boards));
            //23:40以后冻结1小时
            if(intval(date("H"))==23&&intval(date("i"))>=40){
                Redis::expire($cachekey,3705);
            }else{
                Redis::expire($cachekey,805);
            }
        }

        // 生成和获取模拟用户数据
        $fakeBoards = $this->generateFakeLeaderboard();
        foreach ($fakeBoards as &$value){
            $value=(array)$value;
            $value['FaceID']=intval($value['FaceID']);
        }
        // 合并真实和模拟用户数据
        $combinedBoards = array_merge($boards, $fakeBoards);
        $combinedBoards = Util::arraySort($combinedBoards, 'Score', SORT_DESC);

        // 重新计算排名
        foreach ($combinedBoards as $key=>&$value){
            $value['rank'] = $key+1;
            if($value['UserID']==$UserID){
                $myrank=$value['rank'];
            }
        }

        return apiReturnSuc(['ret' =>['myData'=>['rank'=>$myrank],'rank'=>array_slice($combinedBoards,0,100)]]);
    }

    /**
     * 生成模拟用户排行榜数据
     *
     * @return array 模拟用户数据
     */
    private function generateFakeLeaderboard()
    {
        $fakeCacheKey = "Fake_Bill_boardd";
        $fakeChangeCountKey = "Fake_Bill_Change_Count";
        $fakeUserCount = 300; // 模拟用户最多300个
        $now = time();
        $todayDate = date('Ymd');
        $todayKey = "fake_leaderboard_date";

        // 检查是否是新的一天，如果是则重置
        if (!Redis::exists($todayKey) || Redis::get($todayKey) != $todayDate) {
            Redis::del($fakeCacheKey);
            Redis::del($fakeChangeCountKey);
            Redis::set($todayKey, $todayDate);
        }

        // 如果缓存中存在模拟数据且未过期，直接返回
        if (Redis::exists($fakeCacheKey) && Redis::ttl($fakeCacheKey) > 60) {
            $fakeBoards = json_decode(Redis::get($fakeCacheKey), true);

            // 判断是否需要更新模拟数据
            $lastUpdateKey = "fake_leaderboard_last_update";
            $lastUpdate = Redis::exists($lastUpdateKey) ? intval(Redis::get($lastUpdateKey)) : 0;

            $currentHour = intval(date('H'));
            $updateInterval = ($currentHour >= 0 && $currentHour < 10) ? 1800 : 600; // 0-10点每半小时，10点后每10分钟

            if ($now - $lastUpdate >= $updateInterval) {
                $fakeBoards = $this->updateFakeUserScores($fakeBoards);
                Redis::set($lastUpdateKey, $now);
            }

            return $fakeBoards;
        }

        // 生成新的模拟用户数据
        $fakeBoards = [];

        for ($i = 0; $i < $fakeUserCount; $i++) {
            $fakeBoards[] = $this->generateFakeUserData();
        }

        // 按分数排序
        $fakeBoards = Util::arraySort($fakeBoards, 'Score', SORT_DESC);

        // 保存到Redis
        Redis::set($fakeCacheKey, json_encode($fakeBoards));
        Redis::expire($fakeCacheKey, 3600); // 缓存1小时

        // 记录初次更新时间
        Redis::set("fake_leaderboard_last_update", $now);

        return $fakeBoards;
    }

    private function generateFakeUserData()
    {
        $countryCode = env('COUNTRY_CODE', '92'); // 默认使用巴基斯坦区号
        $userID = "99" . mt_rand(1000000, 9999999);
        $gameID = "1" . mt_rand(1000000, 9999999);
        $score = mt_rand(-15000, 35000); // -15000到35000
        return [
            "UserID" => $userID,
            "Score" => $score*100,
            "GameID" => $gameID,
            "NickName" => $this->generateFakeName($countryCode, $gameID),
            "FaceID" => mt_rand(1, 16),
            "rank" => 0, // 初始rank，会在合并后重新计算
            "change_count" => 0 // 变化次数统计
        ];
    }

    /**
     * 更新模拟用户分数
     *
     * @param array $fakeBoards 现有模拟用户数据
     * @return array 更新后的模拟用户数据
     */
    private function updateFakeUserScores($fakeBoards)
    {
        $fakeChangeCountKey = "Fake_Bill_Change_Count";
        $changeCountMap = [];

        // 获取现有的变化次数记录
        if (Redis::exists($fakeChangeCountKey)) {
            $changeCountMap = json_decode(Redis::get($fakeChangeCountKey), true);
        }

        // 确保总体上有增长趋势
        $increasedCount = 0;
        $minIncrease = count($fakeBoards) * 0.3; // 至少30%的用户要增加

        foreach ($fakeBoards as $key => &$user) {
            $userID = $user['UserID'];

            // 初始化变化次数记录
            if (!isset($changeCountMap[$userID])) {
                $changeCountMap[$userID] = 0;
            }

            // 50%的概率进行变化
            if (mt_rand(0, 1) == 1) {

                // 如果变化次数超过70次，则不再变化
                if ($changeCountMap[$userID] >= 70) {
                    continue;
                }

                if(intval(date('H'))>=11){

                    $newScore=intval( $user['Score']*mt_rand(70,140)/100);
                    if($newScore>$user['Score'])$increasedCount++;
                    $user['Score'] = $newScore;
                }else {
                    // 动态回报率，基础值10000
                    $changeAmount = mt_rand(-15000, 35000); // 基础值上下浮动
                    $user['Score'] += $changeAmount * 100;
                    if($changeAmount>0){
                        $increasedCount++;
                    }
                    // 决定是增加还是减少
//                    if ($increasedCount < $minIncrease) {
//                        // 强制增加以满足最低增长要求
//                        $user['Score'] += $changeAmount * 100;
//                        $increasedCount++;
//                    } else {
//                        // 随机增减
//                        if (mt_rand(0, 1) == 1) {
//                            $user['Score'] += $changeAmount * 100;
//                            $increasedCount++;
//                        } else {
//                            $user['Score'] -= $changeAmount * 100;
//
//                        }
//                    }
                }


                // 更新变化次数
                $changeCountMap[$userID]++;
            }
        }

        // 控制模拟用户总数不超过300
        $maxUsers = 300;
        if (count($fakeBoards) < $maxUsers) {
            // 每次增加少量新用户
            $newUsersCount = min(5, $maxUsers - count($fakeBoards));
            for ($i = 0; $i < $newUsersCount; $i++) {
                $fakeBoards[] = $this->generateFakeUserData();
            }
        }

        // 重新按分数排序
        $fakeBoards = Util::arraySort($fakeBoards, 'Score', SORT_DESC);

        // 更新Redis缓存
        Redis::set("Fake_Bill_boardd", json_encode($fakeBoards));
        Redis::expire("Fake_Bill_boardd", 3600);

        // 更新变化次数记录
        Redis::set($fakeChangeCountKey, json_encode($changeCountMap));
        Redis::expire($fakeChangeCountKey, 86400); // 缓存一天

        return $fakeBoards;
    }

    /**
     * 根据国家代码生成模拟用户名
     *
     * @param string $countryCode 国家代码
     * @param string $gameID 游戏ID
     * @return string 生成的用户名
     */
    private function generateFakeName($countryCode, $gameID)
    {
        $lastFourDigits = substr($gameID, -4);

        // 根据国家代码生成不同国家风格的名字
        switch ($countryCode) {
            case '92': // 巴基斯坦
                $pakFirstNames = ['Ahmed', 'Muhammad', 'Ali', 'Hassan', 'Saeed', 'Omar', 'Yousaf', 'Imran', 'Tariq', 'Asif', 'Zain', 'Bilal', 'Faisal', 'Khalid', 'Malik'];
                $pakLastNames = ['Khan', 'Malik', 'Ali', 'Ahmed', 'Shah', 'Qureshi', 'Baloch', 'Siddiqui', 'Raza', 'Javed', 'Iqbal', 'Akbar', 'Aslam'];

                if (mt_rand(0, 1) == 0) {
                    // 有50%概率使用首字母+数字格式
                    return 'U' . $lastFourDigits;
                } else {
                    // 有50%概率使用巴基斯坦名字
                    return $pakFirstNames[array_rand($pakFirstNames)] . substr($pakLastNames[array_rand($pakLastNames)], 0, 1);
                }

            default: // 默认格式
                return 'U' . $lastFourDigits;
        }
    }
    public static function webGameRooms()
    {
        if(!Redis::exists('webgamerooms')) {
            $webgames = DB::table('QPPlatformDB.dbo.GameRoomInfo')->select('ServerID', 'SortID', 'GameID', 'CellScore', 'MinEnterScore')->where('GameID', '>', 9000)->get()->toArray();
            $sorts = [];
            foreach ($webgames as &$value) {
                $value = (array)$value;


                $value['SortID'] = intval($value['SortID']);
                $value['ServerID'] = intval($value['ServerID']);
                $value['MinEnterScore'] = intval($value['MinEnterScore']);
                $value['CellScore'] = intval($value['CellScore']);

                $sorts[$value['GameID']][$value['SortID']] = $value;

            }
            Redis::setex('webgamerooms', 600,json_encode($sorts));
        }else{
            $sorts=Redis::get('webgamerooms');
            $sorts=json_decode($sorts,true);
        }
        return $sorts;

    }
    public function onlineList(Request $request){

        try {
            if (Redis::exists('Online_Real')) {
                $online = Redis::get('Online_Real');
                $online = json_decode($online, true);
            }
            $field = ['gi.GameID', 'gi.Nullity', 'gi.SortID', 'gi.ServerName', 'gi.ServerID'];
            $list = DB::connection('read')->table('QPPlatformDB.dbo.GameRoomInfo as gi')
                ->whereIn('GameID', config('games.openKGame'))
                ->leftJoin('QPTreasureDB.dbo.GameScoreLocker as gl', function ($query) {
                    $query->on('gl.ServerID', 'gi.ServerID')->selectRaw('gl.ServerID')->groupBy('ServerID')->whereRaw('datediff(hh,gl.CollectDate,getdate())<=5');
                })
                ->select($field)
//                ->where('Nullity', 0)
                ->selectRaw('IsNull(count(DISTINCT gl.UserID),0) as game_count')
                ->groupBy($field)
                ->orderBy('gi.GameID', 'asc')
                ->orderBy('gi.ServerName', 'asc');
            if (!isset($online) || Redis::ttl('Online_Real') < 5) {
                if($request->exists("hh")){
                    dd($list->toSql(),json_encode(config('games.openKGame')));
                }else {

                    $list=$list->get()->toArray();
                }


                $online = [];
                foreach ($list as $item) {
                    $item = (array)$item;
                    if (!isset($item) || !isset($item['GameID'])) continue;
                    if (!isset($item['game_count'])) $item['game_count'] = 0;
                    if (isset($online[$item['GameID']])) {
                        if (!isset($online[$item['GameID']][$item['SortID']])) $online[$item['GameID']][$item['SortID']] = 0;
                        $online[$item['GameID']][$item['SortID']] += intval($item['game_count']) ?: mt_rand(100, 200) / 1000;
                    } else {
                        $online[$item['GameID']] = [1 => 0.3, 2 => 0.2, 3 => 0.1];
                        $online[$item['GameID']][$item['SortID']] = intval($item['game_count']) ?: mt_rand(100, 200) / 1000;
                    }
                }


                foreach ($online as $gid => &$ol) {
                    $base=$ol[1]+$ol[2];
                    $ol[1] = intval($base * 168);
                    $ol[2] = intval($base *20);
                    $ol[3] = intval($base *2);
                    if(count($ol)>3){
                        $ol[2] = intval($base * 168);
                        $ol[3] = intval($base *20);
                        $ol[4] = intval($base *2);
                    }
                }
                foreach ($online as $gid => &$ol) {
                    $total=0;
                    foreach ($ol as $count){
                        $total+=$count;
                    }
                    $online[$gid]=['a0'=>$total];
                }

                Redis::set('Online_Real', json_encode($online));
                Redis::expire('Online_Real', 65);
            }


            return apiReturnSuc(['ret' => $online]);
        }catch (\Exception $e){
            Util::WriteLog('online_error',$e->getMessage().$e->getTraceAsString());
            return apiReturnSuc(['ret' =>'']);
        }
    }
}
