<?php

namespace App\Http\Controllers\Game;


use App\Game\AgentLinks;
use App\Game\GlobalUserInfo;
use App\Game\QuickAccountPass;
use App\Game\QuickAccountPassStore;
use App\Game\RePayConfig;
use App\Game\Services\AgentService;
use App\Game\Services\OuroGameService;
use App\Game\Services\RouteService;
use App\Game\WebChannelConfig;
use App\Http\Controllers\Controller;
use App\Http\helper\NumConfig;
use App\IpLocation;
use App\Jobs\AfEvent;
use App\Jobs\IpRiskDetection;
use App\Models\Account\AccountPhone;
use App\Models\AccountsInfo;
use App\Models\GamePhoneVerityCode;
use App\Models\PwaBonusLog;
use App\Models\SystemStatusInfo;
use App\Models\Treasure\GameScoreInfo;
use App\Notification\TelegramBot;
use App\Services\ApkService;
use App\Services\StoredProcedure;
use App\Services\VipService;
use App\Util;
use App\Utility\SetNXLock;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cookie;
use Illuminate\Support\Facades\Crypt;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Redis;
use Illuminate\Support\Facades\Validator;
use PDO;


// use Yansongda\Pay\Log;

class LoginController extends Controller
{

    public function __construct()
    {
    }

    public function LoginByCode(Request $request,$onlyVerify=false)
    {


        $RegisterLocation = $request->country ?? env('COUNTRY_CODE','1');
        $Phone = $request->phone;
        $PhoneCode = $request->code;
        $PhoneCode= preg_replace('/\D/s', '', $PhoneCode);
        if (empty($Phone)) {
            return apiReturnFail(['web.verify.num_empty', 'PhoneNum Empty']);
        }
        if (mb_strlen($PhoneCode) > 6) {
            return apiReturnFail(['web.verify.code_too_long', 'Phone code is too long']);
        }
        $Phone = $RegisterLocation.trim($Phone);


        Log::info('验证电话开始' . $Phone);

        $redisKey = 'LoginByCode_' . $Phone;

        if (!SetNXLock::getExclusiveLock($redisKey)) {
            return apiReturnFail(['web.withdraw.try_again_later', 'Tente novamente mais tarde']);
        }

        if (!is_numeric($PhoneCode)) {
            SetNXLock::release($redisKey);
            Log::info('web.verify.code_incorrect_or_expired LoginByCode is_numeric($PhoneCode)',[$Phone,$PhoneCode]);
            return apiReturnFail(['web.verify.code_incorrect_or_expired', 'O código está incorreto ou o tempo passou']);
        }

        $verifyCode = GamePhoneVerityCode::verifyCode($Phone, $PhoneCode);
        SetNXLock::release($redisKey);
        if ($verifyCode != trim($PhoneCode)) {
            Log::info('web.verify.code_incorrect_or_expired LoginByCode $verifyCode',[$Phone,$PhoneCode]);
            return apiReturnFail(['web.verify.code_incorrect_or_expired', 'O código está incorreto ou o tempo passou']);
        }
        if($onlyVerify)return true;
        GamePhoneVerityCode::clearPhoneCode($Phone);
        $config = RouteService::getChannelConfig($request);
        $user = GlobalUserInfo::query()->where('RegionID', $config->isRegionUnique())->where("Phone", $Phone)->first();
        if ($user) {
            $user = GlobalUserInfo::toWebData($user);
            Util::WriteLog('phone_login',$Phone);
            $this->dispatchIpRiskCheck($user['UserID'] ?? 0);
            return response()->json(apiReturnSuc($user, ['login.success', 'Login bem-sucedido, bem-vindo de volta!']));//->withCookie($this->setLoginCookie($user['sign']));
        } else {
            return apiReturnFail(['web.login.notfound', 'Sua conta não foi encontrada, registre-se ou tente novamente!']);
        }

    }
    public function BindPhone(Request $request)
    {


        $user = GlobalUserInfo::$me;

        $RegisterLocation = $request->country ?? env('COUNTRY_CODE','1');
        $Phone = $request->phone;
        $PhoneCode = $request->code;

        if (empty($Phone)) {
            Log::info('web.verify.num_empty',[$Phone,$PhoneCode]);
            return apiReturnFail(['web.verify.num_empty', 'PhoneNum Empty']);
        }
        if (mb_strlen($PhoneCode) > 6) {
            Log::info('web.verify.code_too_long',[$Phone,$PhoneCode]);
            return apiReturnFail(['web.verify.code_too_long', 'Phone code is too long']);
        }



        $Phone = $RegisterLocation.trim($Phone);

        Log::info('绑定电话开始' . $Phone);

        $redisKey = 'BindPhone_' . $Phone;

        if (!SetNXLock::getExclusiveLock($redisKey)) {
            Log::info('web.withdraw.try_again_later',[$Phone,$PhoneCode]);
            return apiReturnFail(['web.withdraw.try_again_later', 'Tente novamente mais tarde']);
        }




        if (!is_numeric($PhoneCode)) {
            SetNXLock::release($redisKey);
            Log::info('web.verify.code_incorrect_or_expired BindPhone nonum',[$Phone,$PhoneCode]);
            return apiReturnFail(['web.verify.code_incorrect_or_expired', 'O código está incorreto ou o tempo passou']);
        }

        $verifyCode = GamePhoneVerityCode::verifyCode($Phone, $PhoneCode);

        if ($verifyCode != trim($PhoneCode)) {
            SetNXLock::release($redisKey);
            Log::info("web.verify.code_incorrect_or_expired BindPhone $verifyCode",[$Phone,$PhoneCode]);
            return apiReturnFail(['web.verify.code_incorrect_or_expired', 'O código está incorreto ou o tempo passou']);
        }
        GamePhoneVerityCode::clearPhoneCode($Phone);

        $config = RouteService::getChannelConfig($request);
        // 查看手机号是否已经绑定
//        $first = DB::connection('write')->table('QPAccountsDB.dbo.AccountPhone')
//            ->where('PhoneNum', $Phone)
////            ->where('Channel', $user->Channel)
//            ->orWhere('UserID', $user->UserID)
        $first = GlobalUserInfo::query()->where(function ($query) use ($Phone, $user, $config) {
            $query->where(function ($q) use ($Phone, $user) {
                $q->where('RegionID', $user->RegionID??"")->where('Phone', $Phone);
            })->orWhere(function ($q) use ($user) {
                $q->where('UserID', $user->UserID)->where('Phone', '<>', '');
            });
        })->first();

        if ($first) {
            SetNXLock::release($redisKey);
            Log::info('web.verify.already_bound',[$Phone,$PhoneCode]);
//            return apiReturnFail(['web.verify.already_bound', 'O número de telefone foi vinculado']); // 电话号码已绑定
            return apiReturnFail(['web.verify.already_bound', 'O número de telefone foi vinculado'],GlobalUserInfo::getGameUserInfoToWeb('UserID',$first->UserID)); // 电话号码已绑定
        }

//        if (!isset($request->password) || !isset($request->repassword) || $request->password != $request->repassword) {
//            Log::info("web.reg.password_notsame",[$Phone,$PhoneCode]);
//            return apiReturnFail(['web.reg.password_notsame', 'As senhas digitadas duas vezes são inconsistentes, digite novamente!'], '', 2);
//        }

        $PhoneNum = $Phone;

        $Phone = $this->checkPhone($PhoneNum, $RegisterLocation, $request);
        //有错误返回
        if (is_array($Phone) || is_object($Phone)){
            Log::info(json_encode($Phone),[$Phone,$PhoneCode]);
            return $Phone;
        }




        $UserID = $user->UserID;
        $BindDate = Carbon::now()->toDateTimeString();
        $LogonPass = $request->password??$PhoneCode;
        $Channel = $user->Channel;
        $RegionID = $user->RegionID;
        // 绑定手机号
        try {
            AccountPhone::insert(compact('UserID', 'PhoneNum', 'BindDate', 'Channel', 'RegionID'));
        } catch (\Throwable $e) {
            if (stripos($e->getMessage(), 'duplicate key') !== false) {
                return apiReturnFail(['web.verify.already_bound', 'web.verify.already_bound']);
            }
            throw $e;
        }
        GlobalUserInfo::where('GlobalUID', $user->GlobalUID)->update([ 'Phone' => $Phone, 'RegisterLocation' => $RegisterLocation]);
        Log::info('绑定手机号'.'-'.$user->GlobalUID.'-' . $Phone . '-' . $LogonPass . '-' . $UserID);
        // --绑定手机赠送金币
        $SendGold = SystemStatusInfo::OnlyGetCacheValue('BindPhoneReward') ?? 500;
        DB::table('QPRecordDB.dbo.LogProp')->insert(['UserID' => $UserID, 'PropID' => 30000, 'PropNum' => $SendGold, 'Source' => 11, 'Param' => null]);

        OuroGameService::AddScore($UserID, $SendGold, OuroGameService::REASON_BindPhone,false);

        $RecordPlatformDataModel = new \App\Models\RecordPlatformData();
        $RecordPlatformDataModel->BindToday($Channel,$user->RegisterDate);

        AgentService::recordPerformance($UserID, 0,1);

        SetNXLock::release($redisKey);
        return apiReturnSuc(GlobalUserInfo::getGameUserInfoToWeb('UserID', $UserID));
        /**
         *
         * INSERT INTO [QPAccountsDB].[dbo].[AccountPhone] ([UserID],[PhoneNum],[BindDate],[LogonPass],[Channel])values(@UserId,@szPhoneNum,GETDATE(),@strLogonPass,@Channel)
         *
         * --绑定手机赠送金币
         * DECLARE @SendGold int
         * select @SendGold = [StatusValue] from  QPAccountsDB.dbo.SystemStatusInfo where [StatusName] = 'BindPhoneReward'
         * if @SendGold is null
         * begin
         * set @SendGold = 500;
         * end
         *
         * INSERT INTO QPRecordDB.dbo.LogProp(UserID,PropID,PropNum,Source,[Param],RecordData)
         * VALUES(@UserId,30000,@SendGold,11,NULL,GETDATE())
         *
         * EXEC QPRecordDB.dbo.GSP_YN_GR_RecordGameScore
         * @dwUserID=@UserId,
         * @lChangeScore=@SendGold,
         * @nReason = 21,--绑定手机赠送
         * @nServerID=0,
         * @strUniqueCode='',
         * @lRevenue=0,
         * @Type=0
         *
         * update QPTreasureDB.dbo.GameScoreInfo set Score =  Score+@SendGold where @UserId = UserID
         */


    }
//    public function PwaInstalled(Request $request)
//    {
//        $FPID=$request->input("bfp","");
//        $user=$request->user();
//
//        GlobalUserInfo::where('FPID',$FPID)->orWhere('UserID',$user->UserID)->update(['PwaInstalled'=>1]);
//    }
    function generateUUID($userId, $location = '1', $region = null,$Channel=99)
    {
        if(!$region)$region=env('REGION_24680','sa-east');
        // 从随机字节创建基础 UUID
        $randomBytes = bin2hex(random_bytes(3)); // 6个字符
        $randomBytes=str_pad(dechex($Channel),4,'0',STR_PAD_LEFT).$randomBytes;//补上4个channel
        // 缩短区域和语言码以适应 UUID 格式
        $locCode = substr(md5($location), 0, 4); // 4个字符
        $regionCode = substr(md5($region), 0, 4); // 4个字符

        // 确保 UserID 以十六进制形式适应最后部分
        $userIdHex = substr("000000000" . $userId, -10, 10); // 变长，确保适应

        // 构造 UUID
        $uuid = sprintf('%s-%s-%s-%s', $randomBytes, $locCode, $regionCode, $userIdHex);

        return $uuid;
    }

    /// 'PayTotal',
    //        'PayTimes',
    //        'WithdrawTotal',
    //        'LessThan',
    //        'Condition',
    //        'Price',
    //        'Amount',
    //        'Gift',
    //        'TimeLimit',
    //        'Status',
    public function GetUserInfo(Request $request)
    {
        $user = $request->globalUser;
        $user = GlobalUserInfo::toWebData($user);
        self::CheckTimeBonus($user);

        // 计算VIP等级
        //$user['vip'] = VipService::calculateVipLevel($user['UserID'] ?? 0);

        return apiReturnSuc($user);
    }
    public static function CheckTimeBonus(&$user)
    {
        return;
        if(!$user)return;
        $outdatas=null;
        if($user['Channel']==99)return ;
        try {
            $key='repay_temp_'.$user['UserID'];
            if(Redis::exists($key)){
                $lastData=json_decode(Redis::get($key),true);
                if(!isset($lastData['settime'])){
                    $lastData['settime']=time();
                    Redis::set($key, json_encode($lastData));
                }
                $lastData['timeleft']=$lastData['TimeLimit']-(time()-$lastData['settime']);
                unset($lastData['PayTotal'],$lastData['PayTimes'],$lastData['WithdrawTotal'],$lastData['LessThan'],$lastData['id'],$lastData['Condition']);
                $user['bonus_pack'] = $lastData;
            }else {

                //处理新逻辑
                $datas = RePayConfig::CacheDatas();

                if($user['UserID']=='50000005'){
                    $user['Score']=10;
                }

                if (isset($datas) && is_array($datas) && count($datas)) {
                    $datas = array_filter($datas, function ($v) use ($user) {
                        return $user['Score'] < $v['LessThan'];
                    });
                }
                if (isset($datas) && is_array($datas) && count($datas)) {
//                    $userstat = DB::connection('write')->table('QPRecordDB.dbo.RecordUserTotalStatistics')
//                        ->where('UserID', $user['UserID'])->first();

                    $dbh = DB::connection()->getPdo();
                    $stmt = $dbh->prepare(  "EXEC [QPTreasureDB].[dbo].[GSP_GR_QueryUserRechargeInfo] @dwUserID = ".$user['UserID']);
                    $stmt->execute();
                    $userstat = $stmt->fetch(\PDO::FETCH_ASSOC);

                    if($user['UserID']=='50000005'){
                        $userstat['Recharge']=60000;
                        $userstat['Withdraw']=0;
                    }

                    if ($userstat) {
                        $datas = array_filter($datas, function ($v) use ($userstat) {
                            return $userstat['Withdraw'] <= $v['WithdrawTotal'] * NumConfig::NUM_VALUE
                                && $userstat['Recharge'] >= $v['PayTotal']* NumConfig::NUM_VALUE
                                && $userstat['RechargeTimes'] <= $v['PayTimes'];
                        });
                    } else {
                        $datas = [];
                    }
                    $outdatas = $datas;
                    if (isset($datas) && is_array($datas) && count($datas)) {
                        $datas = array_values($datas);
                        $lastData = $datas[0];
                        foreach ($datas as $k => $v) {
                            if ($v['PayTotal'] > $lastData['PayTotal']) {
                                $lastData = $v;
                            }
                        }

                        if (!empty($lastData)) {
                            $lastData['gear'] = DB::table('agent.dbo.recharge_gear')
                                ->where('money', $lastData['Amount'])
                                ->whereBetween('gift_id', [300, 400])
                                ->where('status', 2)
                                ->select('gift_id', 'money', 'give', 'favorable_price', 'second_give')
                                ->first();
                            if(empty($lastData['gear'])){
                                $lastData['gear']=[
                                    'money' => $lastData['Amount'],
                                    'gear' => '[{"id":"2","status":1},{"id":"4","status":-1},{"id":"6","status":1},{"id":"11","status":1},{"id":"15","status":1},{"id":"19","status":1}]',
                                    'status' => 2,
                                    'created_at' => date('Y-m-d H:i:s.v'),
                                    'favorable_price' => $lastData['Amount'],
                                    'image' => '11',
                                    'give' => $lastData['Gift'],
                                    'first_pay' => 0,
                                    'name' => '二次付费',
                                    'gift_id' => DB::table('agent.dbo.recharge_gear')->where('gift_id','<',400)->max('gift_id')+1,
                                    'channels' => '',
                                    'second_give' => 0
                                ];
                                DB::table('agent.dbo.recharge_gear')->insert($lastData['gear']);
                                $lastData['gear']=(object)$lastData['gear'];
                            }
                            $lastData['gear']->id = 28;
                            $lastData['settime']=time();
                            $lastData['timeleft']=$lastData['TimeLimit'];
                            $lastData['gear'] = (array)$lastData['gear'];
                        }
                        unset($lastData['PayTotal'],$lastData['PayTimes'],$lastData['WithdrawTotal'],$lastData['LessThan'],$lastData['id'],$lastData['Condition']);
                        Redis::setex($key, $lastData['TimeLimit'], json_encode($lastData));
                        $user['bonus_pack'] = $lastData;
                    }
                }
            }
        }catch (\Exception $e) {
            TelegramBot::getDefault()->sendMsgWithEnv($e->getMessage().json_encode($outdatas).$e->getTraceAsString());
        }


    }
    public function modiEmail(Request $request)
    {


        $user = $request->globalUser;


        // 自定义错误消息
        $messages = [
            'Email.email'  => 'O formato do email fornecido está incorreto. ',
            'Email.unique' => 'Este endereço de e-mail foi registrado. ',
        ];

        // 验证规则
        $validator = Validator::make($request->all(), [
            'Email' => 'required|email|unique:mysql.webgame.GlobalUserInfo,Email,' . $user->GlobalUID . ',GlobalUID',
        ], $messages);


        if ($validator->fails()) {
            // 返回具体的错误消息
            return apiReturnFail(['web.user.email_fail', $validator->errors()], '', 422);
        }
        $user->update($validator->validate());


        return response()->json(apiReturnSuc(GlobalUserInfo::toWebData($user), ['user.info.modi_success', 'Informação modificada']));

    }

    public function modiPhone(Request $request)
    {
        $user = $request->globalUser;


        // 自定义错误消息
        $messages = [
            'Phone.string' => 'O número de telefone deve estar no formato string. ',
            'Phone.max'    => 'O número de telefone não pode exceder 20 caracteres. ',
            'Phone.unique' => 'Este número de telefone já existe. ',
        ];

        // 验证规则
        $validator = Validator::make($request->all(), [
            'Phone' => 'required|string|max:20|unique:mysql.webgame.GlobalUserInfo,Phone,' . $user->GlobalUID . ',GlobalUID',
        ], $messages);


        if ($validator->fails()) {
            // 返回具体的错误消息
            return apiReturnFail(['web.user.phone_fail', $validator->errors()], '', 422);
        }
        $user->update($validator->validate());


        return response()->json(apiReturnSuc(GlobalUserInfo::toWebData($user), ['user.info.modi_success', 'Informação modificada']));

    }

    public function modiUserInfo(Request $request)
    {
        $user = $request->globalUser;


        $validatedData = Validator::make($request->all(), [
            'NickName'        => 'nullable|string|max:32',
            'FaceID'          => 'nullable|integer|min:1',
            'Gender'          => 'nullable|integer|in:0,1,2',
            'DefaultLanguage' => 'nullable|string|max:10',
            'ThemeColor'      => 'nullable|in:dark,light'
        ], [

            'NickName.string'        => 'O apelido deve ser uma string válida. ',
            'NickName.max'           => 'O apelido não pode exceder 32 caracteres. ',
            'FaceID.integer'         => 'O ID facial deve ser um número inteiro. ',
            'FaceID.min'             => 'O ID facial deve ser maior que 0. ',
            'Gender.integer'         => 'A seleção de gênero é inválida. ',
            'Gender.in'              => 'O gênero deve ser 0 (feminino), 1 (masculino) ou 2 (desconhecido). ',
            'DefaultLanguage.string' => 'O idioma padrão deve ser uma string válida. ',
            'DefaultLanguage.max'    => 'O identificador de idioma padrão não pode exceder 10 caracteres. ',
            'ThemeColor.in'          => 'A cor do tema deve ser "escuro" ou "claro". '
        ]);
        if ($validatedData->fails()) {
            foreach ($validatedData->errors() as $key => $value) {
                return apiReturnFail(['web.modiUserInfo.fail_' . $key, $value[0]], '', 422);
            }
        }
        $validatedData = $validatedData->validate();

        foreach ($validatedData as $key => $value) {
            if (empty($validatedData[$key]) && $validatedData[$key] !== 0) unset($validatedData[$key]);
        }

        if (isset($validatedData['FaceID'])) $validatedData['FaceID'] = ($validatedData['FaceID'] - 1) % 16 + 1;
        if (isset($validatedData['NickName'])) $validatedData['NickName'] = Util::filterNickName($validatedData['NickName']);

        $user->update($validatedData);


        return response()->json(apiReturnSuc(GlobalUserInfo::toWebData($user,true), ['user.info.modi_success', 'Informação modificada']));
    }

    private function checkPhoneCode(Request $request)
    {
        $user=GlobalUserInfo::$me;
        $RegisterLocation = $request->country ?? env('COUNTRY_CODE','55');
        $userPhone="";
        if($user&&isset($user->Phone)&&substr($user->Phone,0,2)==$RegisterLocation){

            $userPhone = explode($RegisterLocation, $user->Phone)[1];
        }

        $Phone = $request->phone??$userPhone;

//        if($Phone!=$userPhone){
//            return apiReturnFail(['web.withdraw.try_again_later', 'Tente novamente mais tarde']);
//        }
        $PhoneCode = $request->code;


        if (empty($Phone)) {
            return apiReturnFail(['web.verify.num_empty', 'PhoneNum Empty']);
        }
        if (mb_strlen($PhoneCode) > 6) {
            return apiReturnFail(['web.verify.code_too_long', 'Phone code is too long']);
        }

        $Phone = $RegisterLocation.trim($Phone);

        Log::info('验证电话开始' . $Phone);

        $redisKey = 'checkPhoneCode_' . $Phone;

        if (!SetNXLock::getExclusiveLock($redisKey)) {
            return apiReturnFail(['web.withdraw.try_again_later', 'Tente novamente mais tarde']);
        }

        if (!is_numeric($PhoneCode)) {
            SetNXLock::release($redisKey);
            Log::info('web.verify.code_incorrect_or_expired checkPhoneCode nonum',[$Phone,$PhoneCode]);
            return apiReturnFail(['web.verify.code_incorrect_or_expired', 'O código está incorreto ou o tempo passou']);
        }

        $verifyCode = GamePhoneVerityCode::verifyCode($Phone, $PhoneCode);
        SetNXLock::release($redisKey);
        if ($verifyCode != trim($PhoneCode)) {
            Log::info('web.verify.code_incorrect_or_expired checkPhoneCode noveri',[$Phone,$PhoneCode]);
            return apiReturnFail(['web.verify.code_incorrect_or_expired', 'O código está incorreto ou o tempo passou']);
        }
        GamePhoneVerityCode::clearPhoneCode($Phone);
        return 1;
    }
    public function forgetPassword(Request $request)
    {
        $check=$this->checkPhoneCode($request);
        if($check!==1){
            return $check;
        }
        $RegisterLocation = $request->country ?? env('COUNTRY_CODE','55');
        $user = GlobalUserInfo::getGameUserInfo("Phone", $RegisterLocation . $request->phone);
        if(!$user||empty($user)){
            return $this->registerUser($request);
            return apiReturnFail(['web.login.notfound', 'Erro de entrada, tente novamente!'], '', 2);
        }
        $request->globalUser=$user;
        return $this->modiPassword($request,false);
    }
    public function forgetInsurePassword(Request $request)
    {
        $check=$this->checkPhoneCode($request);
        if($check!==1){
            return $check;
        }

        return $this->modiInsurePassword($request,false);
    }
    public function modiPassword(Request $request,$checkOldpass=true)
    {
        $user = $request->globalUser;

        if($checkOldpass) {
            $oldpassword = $request->input('oldpassword');
            if (!Hash::check($oldpassword, $user->LogonPass)) {
                return apiReturnFail(['web.user.password_fail', 'A senha original está errada, digite-a novamente.'], '', 2);
            }
        }
        $newpassword = $request->input('newpassword');
        $renewpassword = $request->input('renewpassword');

        if (empty($newpassword) || empty($renewpassword)) {
            return apiReturnFail(['web.user.password_fail', 'A senha original está errada, digite-a novamente.'], '', 3);
        }

        if ($newpassword == $renewpassword) {
            $user->LogonPass = Hash::make($newpassword);
            $user->update(['LogonPass' => $user->LogonPass]);
            return response()->json(apiReturnSuc(GlobalUserInfo::toWebData($user), ['user.password.modi_success', 'Redefinição de senha concluída!']));//->withCookie($this->setLoginCookie($user['sign']));
        } else {
            return apiReturnFail(['web.reg.password_notsame', 'As senhas digitadas duas vezes são inconsistentes, digite novamente!'], '', 2);
        }
    }

    public function modiInsurePassword(Request $request,$checkOldpass=true)
    {
        $user = $request->globalUser;

        if($checkOldpass) {
            $oldpassword = $request->input('oldpassword');
            if (!empty($user->InsurePass) && !Hash::check($oldpassword, $user->InsurePass)) {
                return apiReturnFail(['web.user.paypass_fail', 'A senha original está errada, digite-a novamente.'], '', 2);
            }
        }
        $newpassword = $request->input('newpassword');
        $renewpassword = $request->input('renewpassword');

        if (empty($newpassword) || empty($renewpassword)) {
            return apiReturnFail(['web.user.password_fail', 'A senha original está errada, digite-a novamente.'], '', 3);
        }
        if ($newpassword == $renewpassword) {
            $user->InsurePass = Hash::make($newpassword);
            $user->update(['InsurePass' => $user->InsurePass]);
            return response()->json(apiReturnSuc(GlobalUserInfo::toWebData($user), ['user.password.modi_success', 'Redefinição de senha concluída!']));//->withCookie($this->setLoginCookie($user['sign']));
        } else {
            return apiReturnFail(['web.reg.paypass_notsame', 'As senhas digitadas duas vezes são inconsistentes, digite novamente!'], '', 2);
        }
    }

    public function Logout(Request $request)
    {

        return response()->json(apiReturnSuc('', ['logout.success', 'Você saiu com sucesso.']))->withCookie(self::clearLoginCookie());
    }


    public static function getPwaBonus(Request $request)
    {
        $user=$request->user();
        $haveBonus=Redis::get('pwa_bonus:'.$user->UserID);
        $config = RouteService::getChannelConfig($request);
        if($haveBonus&&$config->BONUS_PWA()>0){
            [$OrgScore,$NowScore]=OuroGameService::AddFreeScore($user->UserID,$config->BONUS_PWA(),OuroGameService::REASON_PwaBonus,false);
            $data=GlobalUserInfo::toWebData($user);
            $data['Score']=$NowScore;
            Redis::del('pwa_bonus:'.$user->UserID);
            PwaBonusLog::addLog([
                'userID' => $user->UserID,
                'GameID' => $user->GameID,
                'Channel' => $user->Channel,
                'bonus_amount' => $config->BONUS_PWA(),
                'org_score' => $OrgScore,
                'now_score' => $NowScore,
                'ip' => $request->ip(),
                'log_date' => date('Y-m-d'),
            ]);

            if(date('Ymd',strtotime($user->RegisterDate)) == date('Ymd')){
                $RecordPlatformDataModel = new \App\Models\RecordPlatformData();
                $RecordPlatformDataModel->PwaToday($user->Channel);
            }

            return response()->json(apiReturnSuc($data, ['user.bonus.pwa_bonus_success', 'Bônus PWA recebido com sucesso!']));
        }else{
            return response()->json(apiReturnFail(['user.bonus.pwa_bonus_fail', 'Você já recebeu o bônus PWA.',$haveBonus,$config->BONUS_PWA()]));
        }

    }

    private function isSequentialOrRepetitive($phoneNumber)
    {
        // 移除国家代码和非数字字符
        $digits = $phoneNumber;//substr($phoneNumber, 2);

        // 检查连号
        if (preg_match('/(\d)\1{5,}/', $digits)) { // 改为检测6个或更多连续相同的数字
            return true;
        }

        // 检查顺子，增加检测递增和递减顺子
        $ascending = true;
        $descending = true;
        for ($i = 0; $i < strlen($digits) - 1; $i++) {
            if (ord($digits[$i + 1]) - ord($digits[$i]) != 1) {
                $ascending = false;
            }
            if (ord($digits[$i]) - ord($digits[$i + 1]) != 1) {
                $descending = false;
            }
        }
        if ($ascending || $descending) {
            return true;
        }
        return false;
    }

    /**
     * @param Request $request
     * @return GlobalUserInfo|false
     */
    public static function checkLogin(Request $request)
    {

//        $sign=$request->cookie('guuid')??$request->sign;
        $sign = $request->sign;
        if ($sign) {
            try {
                $arr = explode('|', Crypt::decryptString($sign));
                $globalUID = $arr[0];
                $timestamp = intval($arr[1]);
                if (time() > $timestamp) return false;
                $user = GlobalUserInfo::getGameUserInfo('GlobalUID', $globalUID);
                if ($user) {
                    if ($arr[2] == substr(md5($user->LogonPass), 0, 6)) {
                        $FPID = $request->input("bfp", "");
                        if (!empty($FPID)) {
                            if (empty($user->FPID)) $user->update(['FPID' => $FPID]);
                            if ($user->LastFPID != $FPID) $user->update(['LastFPID' => $FPID]);
                        }
                        if (empty($user->ShortHashID)) {
                            $ShortHashID = explode('-', $globalUID)[0];
                            $user->update(['ShortHashID' => $ShortHashID]);
                        }
                        GlobalUserInfo::$me = $user;
                        if (intval($request->input('pwa', 0)) == 1) {
                            if (intval($user->PwaInstalled) == 0) {
                                $user->update(['PwaInstalled' => 1]);
                                //s2s
                                AfEvent::dispatch([
                                    'UserID' => $user->UserID,
                                    'event_name' => 'Lead',
                                    'custom_data' => [
                                        'content_name' => 'Install Pwa1',
                                        'status' => 1,
                                    ],
                                ]);
                                $config = RouteService::getChannelConfig($request);
                                if($config->BONUS_PWA()>0){
                                    Redis::setex('pwa_bonus:'.$user->UserID,86400,1);
                                }
                            }
                        }
                        return $user;

                    }
                }

            } catch (\Exception $e) {

            }
        }
        return false;
    }
    private function guestLogin($user,$isRegister=false)
    {
        $qp=QuickAccountPass::query()->where('UserID',$user->UserID)->first();
        if(!$qp){
            $qp=$this->getGustAccount($user->UserID);
            $user->Accounts=$qp['account'];
            $user->LogonPass=Hash::make($qp['password']);
            $user->save();

        }

        $user = GlobalUserInfo::toWebData($user,true);

        if($isRegister)$user['reg'] = 1;
        if($qp){
            if(!is_array($qp))$qp=$qp->toArray();
            $user['account']=$qp['account'];
            $user['password']=$qp['password'];
        }

        $this->dispatchIpRiskCheck($user['UserID'] ?? 0);
        return response()->json(apiReturnSuc($user, ['login.success', 'Login bem-sucedido, bem-vindo de volta!']));
    }

    /**
     * 异步派发 IP 风险检测任务
     * 在用户登录/注册成功后调用，不阻塞响应
     *
     * @param int $userId
     */
    private function dispatchIpRiskCheck($userId)
    {
        $ip = IpLocation::getRealIp();
        if ($ip && $userId) {
            IpRiskDetection::dispatch($userId, $ip);
        }
    }

    public function login(Request $request)
    {
        $type=$request->input('type','id');
        $FPID = $request->input("bfp", "");
        $user=null;

        $config = RouteService::getChannelConfig($request);
        if($type=='guest'){
            //游客模式打开，随时可以登录
            //$user=GlobalUserInfo::where('FPID',$FPID)->where('Phone','')->where('Email','')->first();
            $user=GlobalUserInfo::where('FPID',$FPID)->where('RegionID',$config->isRegionUnique())->first();
            if(!$user){
                return $this->registerUser($request);
            }else{
                return $this->guestLogin($user);
            }
        }

        if (!isset($request->account)) {
            return apiReturnFail(["web.login.account_empty", 'Por favor insira o nome de usuário!']);
        }

        if (!isset($request->password)) {
            return apiReturnFail(['web.login.password_empty', 'Por favor insira a senha!'], '', 302);
        }

        $RegisterLocation = $request->country ?? env('COUNTRY_CODE','55');

        if (strstr($request->account, '@')) {
            $user = GlobalUserInfo::query()->where('RegionID', $config->isRegionUnique())->where("Email", $request->account)->first();
        } else if (is_numeric($request->account)) {
            $user = GlobalUserInfo::query()->where('RegionID', $config->isRegionUnique())->where("Phone", $RegisterLocation . $request->account)->first();
        } else {
            $user = GlobalUserInfo::query()->where('RegionID', $config->isRegionUnique())->where("Accounts", $request->account)->first();
        }


        if ($user) {
            if (Hash::check($request->password, $user->LogonPass)) {
                $user = GlobalUserInfo::toWebData($user,true);
                $this->dispatchIpRiskCheck($user['UserID'] ?? 0);
                return response()->json(apiReturnSuc($user, ['login.success', 'Login bem-sucedido, bem-vindo de volta!']));//->withCookie($this->setLoginCookie($user['sign']));
            } else {
                return apiReturnFail(['web.login.notfound', 'Erro de entrada, tente novamente!'], '', 2);
            }
        } else {
            return apiReturnFail(['web.login.notfound', 'Sua conta não foi encontrada, registre-se ou tente novamente!']);
        }

    }

    private function checkPhone($Phone, $RegisterLocation = '1',Request $request=null)
    {
        $OrgPhone=$Phone;
//        dd($RegisterLocation,$Phone,str_starts_with($Phone,$RegisterLocation),$Phone=explode($RegisterLocation,$Phone));
        if(!empty($RegisterLocation)&&str_starts_with($Phone,$RegisterLocation)){

            $Phone=$OrgPhone;
        }
        if (!empty($Phone)) {
            // 验证规则
            // Remove spaces and dashes from the input
            $Phone = str_replace(['-', ' '], '', $Phone);

            // Check if the number has 11 digits and the third character is 9
            if ($RegisterLocation == env('COUNTRY_CODE','1')) {
//                if (!preg_match('/^\d{2}9\d{8}$/', $Phone)) {
//                    return apiReturnFail(['web.user.phone_fail', 'Not correct phone number'], '', 422);
//                }
            }
            if ($this->isSequentialOrRepetitive($Phone)) {
                return apiReturnFail(['web.user.phone_fail', 'Not correct phone number'], '', 422);
            }

//            if(!str_starts_with($Phone,$RegisterLocation)) {
//                $Phone = $RegisterLocation . $Phone;
//            }
        }

        if (!empty($Phone)) {

            $config = RouteService::getChannelConfig($request);
            $region=$config->isRegionUnique();
            $regionID = $request?$request->user()?$request->user()->RegionID:$region:$region;
            $isExist = GlobalUserInfo::query()
                 ->where('RegionID', $regionID)
                ->where(function ($query) use ($Phone, $OrgPhone) {
                    $query->where("Phone", $Phone)->orWhere('Accounts', $OrgPhone);
                })
                ->first();
            //账户查重
            if ($isExist) {
                if ($request&&Hash::check($request->password, $isExist->LogonPass)) {

                    return $isExist;
                }
                return apiReturnFail(['web.reg.fail_phone_exist', 'O número de telefone já existe, altere-o e tente se cadastrar novamente!']);
            }
        }
        return $Phone;
    }

    public function createGuestAccounts()
    {

        $accs=[];
        for($i=0;$i<100;$i++) {
            $acc = $this->makeGuestAccount();
            while(QuickAccountPassStore::where("account", $acc['account'])->exists()) {
                $acc = $this->makeGuestAccount();
            }
            QuickAccountPassStore::create($acc);
            $accs[]=$acc;
        }
        return ['accs'=>$accs];
    }
    public function getGustAccount($UserID)
    {
        $acc=QuickAccountPass::whereNull('UserID')->first();
        if(!$acc){
            $res=$this->createGuestAccounts();
            $accs=$res['accs'];
            if($accs){
                QuickAccountPass::insert($accs);
            }
            $acc=QuickAccountPass::query()->whereNull('UserID')->first();
        }
        if($acc){
            $acc->update(['UserID' => $UserID]);
        }
        return $acc->toArray();
    }
    public function makeGuestAccount()
    {

// 词库
        $words = ["sun", "moon", "star", "sky", "wind", "fire", "water", "earth","apple","banana","cherry","date","elderberry","fig","grape","honeydew","kiwi","lemon","mango","nectarine","orange","peach","pear","plum","quince","raspberry","strawberry","tangerine","ugli","vanilla","watermelon","xylophone","yam","zucchini","airplane","balloon","camera","drum","eagle","flag","guitar","hat","iceberg","jacket","kite","lamp","mountain","notebook","octopus","penguin","quilt","robot","sunflower","train","umbrella","vase","whale","yacht","zebra","actor","bicycle","carrot","dolphin","elephant","fountain","grape","honey","internet","jungle","koala","lemonade","moose","ninja","octopus","puzzle","quasar","rocket","sunset","trampoline","unicorn","violin","whale","xylophone","yellow","zebra","adventure","bubble","cactus","daisy","envelope","feather","gorilla","horizon","jellyfish","kitchen","lighthouse","mushroom","notebook","orchestra","penguin","quilt","river","snowflake","telescope","universe","vortex","whisper","xenon","yoga","zebra","airport","beach","cucumber","dolphin","eggplant","fishing","grapevine","hiking","jelly","keyboard","lunar","monkey","northern","ocean","pebble","question","robot","scarf","thunder","underwear","vivid","windmill","xylophone","yogurt","zoo","amethyst","butterfly","cloud","dream","emerald","frost","garden","harmony","island","jigsaw","kaleidoscope","lily","melody","nectar","obsidian","parrot","quilt","rainbow","storm","twilight","vortex","whistle","xenon","yarn","zeppelin","antelope","bridge","cobweb","diamond","energy","feather","giraffe","horizon","icicle","jungle","kettle","lemonade","morning","nightfall","octagon","peacock","quasar","riddle","snowman","tulip","unicorn","violet","wonder","xenon","yellow","zodiac","albatross","bamboo","carpet","dandelion","echo","flamingo","galaxy","honeycomb","illusion","jellybean","knight","lighthouse","moonlight","ninja","orchestra","penguin","quill","robot","sunrise","tiger","umbrella","vampire","wisteria","xylophone","yawn","zebra","acrobat","beetle","coral","dusk","elm","frost","grace","horizon","igloo","jacket","kite","lamb","meadow","nail","owl","prism","quince","raven","sand","telescope","universe","vacuum","waterfall","xylophone","yacht","zenith","alphabet","breeze","crystal","dawn","eagle","festival","glow","horizon","ivory","jewel","knob","lemon","magnet","noon","oak","path","quest","rose","skyline","trail","umbrella","vortex","wave","xylophone","yellow","zephyr","abstract","beetle","cherry","dolphin","enigma","flame","giraffe","horizon","ink","jewel","kaleidoscope","lily","matrix","neptune","oasis","puzzle","quartz","rain","snowflake","tulip","ufo","vortex","whale","xylophone","yarn","zeppelin","apple","amazon","google","microsoft","facebook","twitter","netflix","sony","samsung","intel","nike","adidas","coca-cola","pepsi","oracle","ibm","hp","dell","nvidia","twitter","afghanistan","brazil","canada","denmark","egypt","france","germany","hungary","india","japan","kenya","luxembourg","morocco","nigeria","oman","portugal","qatar","russia","spain","turkey","ukraine","vietnam","albert","isaac","marie","charles","nelson","martin","george","abraham","leo","vincent","john","michael","james","robert","david","mary","jennifer","linda","patricia","susan"];
        $numbers = range(0, 999);

// 生成账号和密码

        $word1 = $words[array_rand($words)];
//            $word2 = $words[array_rand($words)];
        $number = str_pad($numbers[array_rand($numbers)], 2, '0', STR_PAD_LEFT);

        $account= $word1 . $number ;

        $word = $words[array_rand($words)];
        $number = str_pad($numbers[array_rand($numbers)], 2, '0', STR_PAD_LEFT);
        $password= $word . $number;


        return compact('account', 'password');


    }
    public function getUserByFPID($FPID)
    {

        $user=GlobalUserInfo::getGameUserInfo('FPID', $FPID);
        return $user;
    }
    private $maxFpsidLimit=2;
    public function registerUser(Request $request, $regByGuest = false)
    {
        //type=id,phone,sms,mail,guest
        $type=$request->input('type',"id");

        if (!$regByGuest&&$type!='guest') {
            if (!isset($request->email) && !isset($request->phone)&&!isset($request->account)) {
                return apiReturnFail(["web.reg.account_empty", 'Por favor insira o nome de usuário!']);
            }

            if (!isset($request->password) || !isset($request->repassword) || $request->password != $request->repassword) {
                return apiReturnFail(['web.reg.password_notsame', 'As senhas digitadas duas vezes são inconsistentes, digite novamente!'], '', 2);
            }
        }
        $FPID = $request->input("bfp", "");

        if($type=='sms'){
            $verifyRes=$this->LoginByCode($request,true);
            //报错
            if(is_array($verifyRes))return $verifyRes;
        }else{
            //把数据卡限制住
//            if (GlobalUserInfo::where('FPID',$FPID)->count() > $this->maxFpsidLimit) {
//                $allAcc=GlobalUserInfo::where('FPID',$FPID)->get()->toArray();
//                $reqs=$request->all();
//                Util::WriteLog('maxreg',compact('allAcc','reqs'));
//                return apiReturnFail(['web.reg.fail_ipmax', 'Too many register requests!']);
//            }
        }



        if (empty($FPID)) {
            return apiReturnFail(['web.reg.fail_phone_exist', 'O número de telefone já existe, altere-o e tente se cadastrar novamente!']);
        }

        //获取默认配置
        $config = RouteService::getChannelConfig($request);
        //游客注册检查是否已经注册
        if($type=='guest'){
            $where = [];
            $where[] = ['FPID', $FPID];
            $where[] = ['Phone', ''];
            $where[] = ['Email', ''];
            $where[] = ['RegionID', $config->isRegionUnique()];

            $guestUser=GlobalUserInfo::where($where)->first();

            if($guestUser){
                //存在，直接返回去
                return $this->guestLogin($guestUser);
            }
        }

        $login_ip = IpLocation::getRealIp();
        $RegisterLocation = $request->country ?? env('COUNTRY_CODE',55);
        $ServerRegion = env('REGION_24680','sa-east');
        $Language = $request->lang ?? $request->getLocale();
        $Phone = $request->phone ?? "";

        $Phone = $this->checkPhone($Phone, $RegisterLocation,$request);
        //有错误返回
        if (is_array($Phone)) {
            return $Phone;
        }else if(is_object($Phone)&&isset($Phone->GlobalUID)){
            //原来就存在，直接返回
            $guser = GlobalUserInfo::toWebData($Phone,true);
            $guser['reg'] = 1;
            return response()->json(apiReturnSuc($guser, ['reg.success', 'Registro realizado com sucesso!']));
        }

        if (isset($request->email) && strstr($request->email, '@')) {
            $isExist = GlobalUserInfo::query()->where("Email", $request->email)->exists();
            //账户查重
            if ($isExist) {
                return apiReturnFail(['web.reg.fail_email_exist', 'O e-mail já existe, altere-o e tente se cadastrar novamente!']);
            }
        }


        $redisKey = 'register_' . $FPID;
        if (!SetNXLock::getExclusiveLock($redisKey)) {
            return apiReturnFail(['web.withdraw.try_again_later', 'Tente novamente mais tarde']);
        }

        $Channel = 0;

        //保持邀请和被邀请的渠道序列统一
        $ActCode = $request->input('act');
        if(strstr($ActCode,'http')){
            $ActCode=explode('http',$ActCode)[0];
        }

        $ReferrType = 0;
        if ($ActCode) {
            //使用邀请的Code来保持邀请被邀请的用户注册渠道一致性
            $link = AgentLinks::getByCode($ActCode);
            if ($link) {
                $inviter = AccountsInfo::where('UserID', $link->UserID)->first();
                if($inviter&&is_object($inviter)) {
                    $Channel = $inviter->Channel;
                    $ReferrType = 2;
                }
            }
        }
        if(!$Channel){

            //非游客注册
            while($config->isGuestOpen()&&!$regByGuest){
                RouteService::clearChannelConfig();
                $config = RouteService::getChannelConfig($request);
            }

            $Channel = $config->Channel;
            if($Channel!=env('REGION_24680_DEFAULT_CHANNEL',100))$ReferrType = 1;

        }else{

            //先搜索本地配置
            $config = WebChannelConfig::getByChannel($Channel);

        }
        $Package = $config->PackageName;

        if ($config) {
            //每小时对齐两个表的包名
            if(!Redis::exists('ChannelPackageName'.$Channel)) {
                $pack = DB::table('QPPlatformDB.dbo.ChannelPackageName')->where('Channel', $Channel)->select('PackageName')->first();
                if ($pack) {
                    Redis::setex('ChannelPackageName' . $Channel, 3600, $Package);
                    if ($Package != $pack->PackageName) {
                        DB::table('QPPlatformDB.dbo.ChannelPackageName')->where('Channel', $Channel)->update(['PackageName' => $Package]);
                    }
                }
            }
        }
        $account= $request->account??$request->email ?? $request->phone ?? $FPID;

        //注册到游戏服务器
        $user = $this->registerAccountInfo($request, $Package, $Channel,$account);

        //返回错误
        if (is_array($user) && !isset($user['UserID'])) {
            SetNXLock::release($redisKey);
            return $user;
        }
        if (!$user) {
            SetNXLock::release($redisKey);
            return apiReturnFail(['web.withdraw.try_again_later', 'Pausa de login']);
        }
        //代理注册,保留号段10000-100000
        if($request->input('isagent',0)=='24680'){
            $oldid=$user['UserID'];

            $newid=AccountsInfo::whereBetween('UserID',[10000,100000])->max('UserID')??10000;
            $newid++;
            $acc=AccountsInfo::find($oldid);
            $newacc=$acc->toArray();
            $acc->delete();
            $newacc['UserID']=$newid;
            $pdo = DB::connection('write')->getPdo();

            $pdo->setAttribute(PDO::SQLSRV_ATTR_DIRECT_QUERY, true);
            DB::connection('write')->unprepared("set identity_insert QPAccountsDB.dbo.AccountsInfo on;");
            DB::connection('write')->table('QPAccountsDB.dbo.AccountsInfo')->insert($newacc);
            DB::connection('write')->unprepared("set identity_insert QPAccountsDB.dbo.AccountsInfo off;");
            $pdo->setAttribute(PDO::SQLSRV_ATTR_DIRECT_QUERY, false);
            $old=['UserID'=>$oldid];$new=['UserID'=>$newid];
            DB::connection('write')->table('QPAccountsDB.dbo.UserAgent')->where($old)->update($new);
            DB::connection('write')->table('QPTreasureDB.dbo.GameScoreInfo')->where($old)->update($new);
            $user['UserID']=$newid;
        }

        $UserID = $user['UserID'];
        $GameID = $user['GameID'];


        $password=$request->password;

        $globalUserInfo = GlobalUserInfo::getGameUserInfo('UserID', $UserID);
        if ($globalUserInfo) {
            $GlobalUID = $globalUserInfo->GlobalUID;
        } else {

            if($type=='guest'){
                //改成从中心区获取idpass
                $idps=$this->getGustAccount($UserID);
                $account=$idps['account'];
                $password=$idps['password'];
            }

            $GlobalUID = $this->generateUUID($UserID, $RegisterLocation, $ServerRegion,$Channel??99);
            $ShortHashID = explode('-', $GlobalUID)[0];
            //先搞定userid
            $globalUserInfo = new GlobalUserInfo([
                'UserID'           => $UserID,
                'GameID'           => $GameID,
                'FF'               => $request->input('ff', ''),
                'FPID'             => $FPID,
                'LastFPID'         => $FPID,
                'ShortHashID'      => $ShortHashID,
                'GlobalUID'        => $GlobalUID,
                'Accounts'         => $account, // Assuming email is received from request
                'Email'            => $request->email ?? '', // Assuming email is received from request
                'Phone'            => $Phone, // Assuming email is received from request
                'LogonPass'        => Hash::make($password),
                'LogonIP'          => $login_ip,
                'Gender'           => 1,
                'RegisterIP'       => $login_ip,
                'RegisterLocation' => $RegisterLocation,
                'ServerRegion'     => $ServerRegion,
                'DefaultLanguage'  => $Language,
                'Channel'          => $Channel??99,
                'RegionID'         => $config->isRegionUnique(),
                'ReferrType'       => $ReferrType,
                'RegisterDate'     => date('Y-m-d H:i:s'),
                'InsurePass'       => '',
                'UserRight'        => 0,
                'Level'            => 0,
                'Exp'              => 0,
                'FaceID'           => $user['FaceID'],
                'NickName'         => $user['NickName'],
                'Registed'         =>1,
                'PwaInstalled'     =>$request->input('pwa',0),
                //            'InsurePass' => Hash::make($request->insurePassword),
                // Add other fields as needed
            ]);
            try {
                $globalUserInfo->save();
            } catch (\Exception $exception) {
                Log::error($exception->getMessage());

            }
        }
        GlobalUserInfo::$me=$globalUserInfo;
        if($Channel==env('REGION_24680_DEFAULT_CHANNEL',100)){
            Util::WriteLog('c99',json_encode($_SERVER));
        }
        //注册钱数要归0
//        $newRegGolds=$config->isRegZeroMoneyOpen()?0:$config->BONUS_REG();
//        GameScoreInfo::query()->where('UserID', $UserID)->update(['Score'=>$newRegGolds]);

        $agentUser = AgentService::SetUserAgent($GlobalUID, $UserID, $ActCode);
        SetNXLock::release($redisKey);

        if ($regByGuest) {
            return GlobalUserInfo::getGameUserInfo("UserID", $UserID);
        }

        $cookieParam = $request->input('cookie', '');
        $fbclid = ApkService::extractFbclid($cookieParam);
        ApkService::bindCookie($globalUserInfo, $request->input('s_k', ''), $fbclid, $cookieParam);

        $guser = GlobalUserInfo::toWebData($globalUserInfo,true);

//        if($agentUser->Higher1ID){
//            //获取邀请者信息
//            $inviter=AccountsInfo::where('UserID',$agentUser->Higher1ID)->first();
//        }
        $guser['reg'] = 1;

        if($type=='guest'){
            $guser['account'] = $account;
            $guser['password'] = $password;
        }

        $defaultGameId = 931;
        $recommendGame = '/game/' . $defaultGameId;
        // 如果用户信息存在，根据GameID的最后一位数字查询映射关系
        if ($guser && isset($guser['GameID'])) {
            $gameId = (string)$guser['GameID'];
            $lastDigit = (int)substr($gameId, -1); // 获取最后一位数字

            // 查询映射关系（带缓存）
            $cacheKey = 'game_number_mapping:' . $lastDigit;
            $mapping = null;
            // 尝试从缓存获取
            $cached = Redis::get($cacheKey);
            if ($cached !== null) {
                $decoded = json_decode($cached, true);
                if (is_array($decoded) && !empty($decoded)) {
                    $mapping = (object)$decoded;
                }
            }
            if(!$mapping){
                $mapping = DB::table('agent.dbo.game_number_mapping')
                    ->where('number', $lastDigit)
                    ->first();

                Redis::setex($cacheKey, $mapping ? 86400 : 300, json_encode($mapping ?: []));
            }

            if ($mapping && isset($mapping->game_id) && $mapping->game_id) {
                $defaultGameId = $mapping->game_id;
                $recommendGame = '/game/' . $mapping->game_id;
            }
        }
        $guser['recommendGame'] = $recommendGame;

        AccountsInfo::where('UserID', $UserID)->update(['UserMedal' => $defaultGameId ]);

        Util::WriteLog('register_params',[$request,$guser]);
        //s2s上报
        AfEvent::dispatch([
            'UserID' => $UserID,
            'event_name' => 'CompleteRegistration',
            'custom_data' => [
                'content_name' => 'register_success',
                'status' => 1,
            ],
        ]);
        if($request->input('pwa',0)){
            AfEvent::dispatch([
                'UserID' => $UserID,
                'event_name' => 'Lead',
                'custom_data' => [
                    'content_name' => 'Install Pwa2',
                    'status' => 1,
                ],
            ]);
        }
        $this->dispatchIpRiskCheck($UserID);
        return response()->json(apiReturnSuc($guser, ['reg.success', 'Registro realizado com sucesso!']));//->withCookie($this->setLoginCookie($guser['sign']));
    }


    public function registerUserNew(Request $request, $regByGuest = true)
    {
        //type=id,phone,sms,mail,guest
        $type=$request->input('type',"id");
        $FPID = $request->input("bfp", "");

        if (empty($FPID)) {
            return apiReturnFail(['web.reg.fail_phone_exist', 'O número de telefone já existe, altere-o e tente se cadastrar novamente!']);
        }

        $config = RouteService::getChannelConfig($request);


        $where = [];
        $where[] = ['FPID', $FPID];
//        $where[] = ['Phone', ''];
//        $where[] = ['Email', ''];
        $where[] = ['RegionID', $config->isRegionUnique()];

        $guestUser=GlobalUserInfo::where($where)->first();


        if($guestUser){
            //存在，直接返回去
            return $this->guestLogin($guestUser);
        }

        $login_ip = IpLocation::getRealIp();
        $RegisterLocation = $request->country ?? env('COUNTRY_CODE',1);
        $ServerRegion = env('REGION_24680','sa-east');
        $Language = $request->lang ?? $request->getLocale();
        $Phone = $request->phone ?? "";
        if (is_numeric($Phone) && !str_starts_with($Phone, $RegisterLocation)) {
            //如果是纯数字且不以国家码开头，自动加上国家码
            $Phone = $RegisterLocation . $Phone;
        }

        $Phone = $this->checkPhone($Phone, $RegisterLocation,$request);
        //有错误返回
        if (is_array($Phone)) {
            return $Phone;
        }else if(is_object($Phone)&&isset($Phone->GlobalUID)){
            //原来就存在，直接返回
            $guser = GlobalUserInfo::toWebData($Phone,true);
            $guser['reg'] = 1;
            return response()->json(apiReturnSuc($guser, ['reg.success', 'Registro realizado com sucesso!']));
        }



        $redisKey = 'register_' . $FPID;
        if (!SetNXLock::getExclusiveLock($redisKey)) {
            return apiReturnFail(['web.withdraw.try_again_later', 'Tente novamente mais tarde']);
        }

        $Channel = 0;

        //保持邀请和被邀请的渠道序列统一
        $ActCode = $request->input('act');
        if(strstr($ActCode,'http')){
            $ActCode=explode('http',$ActCode)[0];
        }
        $Package = 'com.uswin.game777';
        $ReferrType = 0;
        if ($ActCode) {
            //使用邀请的Code来保持邀请被邀请的用户注册渠道一致性
            if (strlen($ActCode) > 6) {
                $ActCode = substr($ActCode, 0, 6);
            }
            $link = AgentLinks::getByCode($ActCode);
            if ($link) {
                $inviter = AccountsInfo::where('UserID', $link->UserID)->first();
                if($inviter&&is_object($inviter)) {
                    $Channel = $inviter->Channel;
                    $ReferrType = 2;
                }
            }
        }
        if(!$Channel){

            //获取默认配置
//            $config = RouteService::getChannelConfig($request);
            //非游客注册
//            while($config->isGuestOpen()&&!$regByGuest){
//                RouteService::clearChannelConfig();
//                $config = RouteService::getChannelConfig($request);
//            }

            $Channel = $config->Channel;
            if($Channel!=env('REGION_24680_DEFAULT_CHANNEL',100))$ReferrType = 1;

        }else{

            //先搜索本地配置
            $config = WebChannelConfig::getByChannel($Channel);

        }
        $Package = $config->PackageName;

        if ($config) {
            //每小时对齐两个表的包名
            if(!Redis::exists('ChannelPackageName'.$Channel)) {
                $pack = DB::table('QPPlatformDB.dbo.ChannelPackageName')->where('Channel', $Channel)->select('PackageName')->first();
                if ($pack) {
                    Redis::setex('ChannelPackageName' . $Channel, 3600, $Package);
                    if ($Package != $pack->PackageName) {
                        DB::table('QPPlatformDB.dbo.ChannelPackageName')->where('Channel', $Channel)->update(['PackageName' => $Package]);
                    }
                }
            }
        }
        $account= $request->account??$request->email ?? $request->phone ?? $FPID;

        //注册到游戏服务器
        $user = $this->registerAccountInfo($request, $Package, $Channel,$account);

        //返回错误
        if (is_array($user) && !isset($user['UserID'])) {
            SetNXLock::release($redisKey);
            return $user;
        }
        if (!$user) {
            SetNXLock::release($redisKey);
            return apiReturnFail(['web.withdraw.try_again_later', 'Pausa de login']);
        }
        //代理注册,保留号段10000-100000

        $UserID = $user['UserID'];
        $GameID = $user['GameID'];


        $password=$request->password;

        $globalUserInfo = GlobalUserInfo::getGameUserInfo('UserID', $UserID);
        if ($globalUserInfo) {
            $GlobalUID = $globalUserInfo->GlobalUID;
        } else {

//            if($type=='guest'){
//                //改成从中心区获取idpass
//                $idps=$this->getGustAccount($UserID);
//                $account=$idps['account'];
//                $password=$idps['password'];
//            }

            $GlobalUID = $this->generateUUID($UserID, $RegisterLocation, $ServerRegion,$Channel??99);
            $ShortHashID = explode('-', $GlobalUID)[0];
            //先搞定userid
            $globalUserInfo = new GlobalUserInfo([
                'UserID'           => $UserID,
                'GameID'           => $GameID,
                'FF'               => $request->input('ff', ''),
                'FPID'             => $FPID,
                'LastFPID'         => $FPID,
                'ShortHashID'      => $ShortHashID,
                'GlobalUID'        => $GlobalUID,
                'Accounts'         => $account, // Assuming email is received from request
                'Email'            => $request->email ?? '', // Assuming email is received from request
                'Phone'            => $Phone ?? '', // Assuming phone is received from request
                'LogonPass'        => Hash::make($password),
                'LogonIP'          => $login_ip,
                'Gender'           => 1,
                'RegisterIP'       => $login_ip,
                'RegisterLocation' => $RegisterLocation,
                'ServerRegion'     => $ServerRegion,
                'DefaultLanguage'  => $Language,
                'Channel'          => $Channel??100,
                'RegionID'         => $config->isRegionUnique(),
                'ReferrType'       => $ReferrType,
                'RegisterDate'     => date('Y-m-d H:i:s'),
                'InsurePass'       => '',
                'UserRight'        => 0,
                'Level'            => 0,
                'Exp'              => 0,
                'FaceID'           => $user['FaceID'],
                'NickName'         => $user['NickName'],
                'Registed'         =>1,
                'PwaInstalled'     =>$request->input('pwa',0),
                //            'InsurePass' => Hash::make($request->insurePassword),
                // Add other fields as needed
            ]);
            try {
                $globalUserInfo->save();
            } catch (\Exception $exception) {
                Log::error($exception->getMessage());

            }
        }
        GlobalUserInfo::$me=$globalUserInfo;
        if($Channel==env('REGION_24680_DEFAULT_CHANNEL',100)){
            Util::WriteLog('c99',json_encode($_SERVER));
        }
        //注册钱数要归0
//        $newRegGolds=$config->isRegZeroMoneyOpen()?0:$config->BONUS_REG();
//        GameScoreInfo::query()->where('UserID', $UserID)->update(['Score'=>$newRegGolds]);

        $agentUser = AgentService::SetUserAgent($GlobalUID, $UserID, $ActCode);
        SetNXLock::release($redisKey);

//        if ($regByGuest) {
//            return GlobalUserInfo::getGameUserInfo("UserID", $UserID);
//        }

        $cookieParam = $request->input('cookie', '');
        $fbclid = ApkService::extractFbclid($cookieParam);
        ApkService::bindCookie($globalUserInfo, $request->input('s_k', ''), $fbclid, $cookieParam);
        $guser = GlobalUserInfo::toWebData($globalUserInfo,true);

//        if($agentUser->Higher1ID){
//            //获取邀请者信息
//            $inviter=AccountsInfo::where('UserID',$agentUser->Higher1ID)->first();
//        }
        $guser['reg'] = 1;
//
//        if($type=='guest'){
//            $guser['account'] = $account;
//            $guser['password'] = $password;
//        }

        $defaultGameId = 931;
        $recommendGame = '/game/' . $defaultGameId;
        $guser['recommendGame'] = $recommendGame;
        // 如果用户信息存在，根据GameID的最后一位数字查询映射关系
        if ($guser && isset($guser['GameID'])) {
            $gameId = (string)$guser['GameID'];
            $lastDigit = (int)substr($gameId, -1); // 获取最后一位数字

            // 查询映射关系（带缓存）
            $cacheKey = 'game_number_mapping:' . $lastDigit;
            $mapping = null;
            $cacheHit = false;

            // 尝试从缓存获取
            $cached = Redis::get($cacheKey);
            if ($cached !== null) {
                $decoded = json_decode($cached, true);
                // 如果解码成功且不是空数组，说明有数据
                if (is_array($decoded) && !empty($decoded)) {
                    $mapping = (object)$decoded; // 转换为对象以保持兼容性
                    $cacheHit = true;
                } elseif ($decoded === []) {
                    // 空数组表示数据库中没有记录，已缓存，直接跳过查询
                    $cacheHit = true;
                    $mapping = null;
                }
            }

            // 缓存未命中，查询数据库
            if (!$cacheHit) {
                $mapping = DB::connection('write')
                    ->table('agent.dbo.game_number_mapping')
                    ->where('number', $lastDigit)
                    ->first();

                // 存入缓存，24小时过期
                if ($mapping) {
                    Redis::setex($cacheKey, 86400, json_encode($mapping));
                } else {
                    // 即使不存在也缓存，避免频繁查询，缓存5分钟
                    Redis::setex($cacheKey, 300, json_encode([]));
                }
            }

            if ($mapping && !empty($mapping) && isset($mapping->game_id) && $mapping->game_id) {
                $defaultGameId = $mapping->game_id;
                $recommendGame = '/game/' . $mapping->game_id;
            }
            $guser['recommendGame'] = $recommendGame;
        }
        $mobileBand = '';
        $ua = $request->userAgent();
        if (stripos($ua, 'iPhone') !== false) {
            $mobileBand = 'iPhone';
        } else if (stripos($ua, 'iPad') !== false) {
            $mobileBand = 'iPad';
        } else if (stripos($ua, 'Android') !== false) {
            $mobileBand = 'Android';
        } else if (stripos($ua, 'Windows') !== false) {
            $mobileBand = 'PC';
        } else if (stripos($ua, 'Mac') !== false) {
            $mobileBand = 'Mac';
        }
        $accUpdate = ['UserMedal' => $defaultGameId];
        if ($mobileBand){
            $accUpdate['LastLogonMobile'] = $mobileBand;
        }

        AccountsInfo::where('UserID', $UserID)->update($accUpdate);

        Util::WriteLog('register_params',[$request,$guser,['Package' => $Package]]);

        //s2s上报
        AfEvent::dispatch([
            'UserID' => $UserID,
            'event_name' => 'CompleteRegistration',
            'custom_data' => [
                'content_name' => 'register_success',
                'status' => 1,
            ],
        ]);
        if($request->input('pwa',0)){
            AfEvent::dispatch([
                'UserID' => $UserID,
                'event_name' => 'Lead',
                'custom_data' => [
                    'content_name' => 'Install Pwa2',
                    'status' => 1,
                ],
            ]);
        }

        $this->dispatchIpRiskCheck($UserID);
        return response()->json(apiReturnSuc($guser, ['reg.success', 'Registro realizado com sucesso!']));//->withCookie($this->setLoginCookie($guser['sign']));
    }

    public function registerAccountInfo(Request $request, $PackageName = 'com.uswin.game777', $Channel = 0,$account=null)
    {
        if (empty($Channel) || !$Channel) $Channel = env('REGION_24680_DEFAULT_CHANNEL',100);

        //防止串行
        $app=DB::connection('write')->table('QPPlatformDB.dbo.ChannelPackageName')->where('Channel', $Channel)->first();
        if($app)$PackageName=$app->PackageName;

        $FPID = $request->input("bfp", "");

        $Accounts = $account??$FPID ?? $request->adid ?? $request->gaaid ?? md5(random_bytes(30));
        $SpreadID = 0;
        $Password = $request->password ?? md5(random_bytes(30));
        $FaceI = mt_rand(1, 16);
        $Gender = $request->gender ?? 0;

        $InsurePass = "";


        $Phone = $request->phone ?? "";
        $ip = $request->header("X_REAL_IP") ?? $request->ip();
        $MachineID = $Accounts;

        $cbType = 1;
        if (!empty($Phone)) {
            $cbType = 2;
        }

        $res = StoredProcedure::ALLRegisterAccounts(
            $Accounts,
            '1',
            $SpreadID,
            $Password,
            $InsurePass,
            $FaceI,
            $Gender,
            1,
            $Phone,
            $ip,
            $MachineID,
            $cbType,
            $Channel,
            $PackageName
        );

        Log::info('注册结果  ' . json_encode($res));
        $ReturnValue = $res['ReturnValue'] ?? 0;
        if (is_bool($res)) {
            $ReturnValue = 3;
        }
        $message = '';
        if ($ReturnValue > 0) {
            switch ($ReturnValue) {
                case 1: # 注册暂停
                    return apiReturnFail(['web.reg.fail_suspend', 'Registro suspenso']);
                    break;
                case 2: # 登录暂停
                    return apiReturnFail(['web.reg.fail_stoplogin', 'Pausa de login']);
                    break;
                case 3: # 登录暂停
                    return apiReturnFail(['web.withdraw.try_again_later', 'Pausa de login']);
                    break;
                case 201: # accounts已经存在
                case 301:
                case 8: # 帐号已存在，请换另一帐号名字尝试再次注册！
                    $exist_user = AccountsInfo::where('Accounts', $Accounts . $Channel)->first();

                    if ($exist_user) {
                        $isexitGuser = GlobalUserInfo::getGameUserInfo('UserID', $exist_user->UserID);
                        if ($isexitGuser) {
                            return apiReturnFail(['web.reg.fail_account_exist', 'A conta já existe, altere outro nome de conta e tente se registrar novamente!'],compact('res','Accounts'));
                        } else {
                            $res = $exist_user;
                        }
                    } else {
                        return apiReturnFail(['web.withdraw.try_again_later', 'Pausa de login']);
                    }
                    break;
                case 10: # IP最大注册数量
                    return apiReturnFail(['web.reg.fail_ipmax', 'Mesmo IP não pode registrar várias contas']);
                    break;
            }
        }
        Util::WriteLog('login', $res);
//        $user=AccountsInfo::query()->where("Accounts",$Accounts)->first();
//        Util::WriteLog('login',$user);
        return $res;
    }

    protected function setLoginCookie($encryptedGlobalUID)
    {
//        $encryptedGlobalUID = Crypt::encryptString($GlobalUID);
        $cookie = Cookie::make('guuid', $encryptedGlobalUID, 60 * 24 * 365, "/", null, true, false, false, 'None');
        return $cookie;
    }


    static public function clearLoginCookie()
    {

        $cookie = Cookie::make('guuid', "", -60, "/", null, true, false, false, 'None');
        return $cookie;
    }

}
