<?php

namespace app\api\controller\v1;

use addons\webman\model\BankList;
use addons\webman\model\Channel;
use addons\webman\model\ChannelRechargeMethod;
use addons\webman\model\ChannelRechargeSetting;
use addons\webman\model\Currency;
use addons\webman\model\DrawRecord;
use addons\webman\model\Game;
use addons\webman\model\PlayerRechargeRecord;
use addons\webman\model\Notice;
use addons\webman\model\Player;
use addons\webman\model\PlayerBank;
use addons\webman\model\PlayerDeliveryRecord;
use addons\webman\model\PlayerWithdrawRecord;
use addons\webman\model\Prize;
use addons\webman\model\SepayRecharge;
use app\exception\PromoterCheckException;
use app\exception\GameException;
use app\exception\PlayerCheckException;
use app\service\SklPayServices;
use Illuminate\Support\Carbon;
use Illuminate\Support\Str;
use Respect\Validation\Exceptions\AllOfException;
use Respect\Validation\Validator as v;
use support\Db;
use support\Request;
use support\Response;
use think\Exception;
use Tinywan\Jwt\JwtToken;
use addons\webman\model\PhoneSmsLog;
use support\Redis;
use Webman\Push\PushException;

class PlayerController
{
    /** 排除验签 */
    protected $noNeedSign = [];

    /**
     * 登录接口
     * @param Request $request
     * @return Response
     * @throws \Exception
     */
    public function login(Request $request): Response
    {
        $validator = v::key('phone', v::stringType()->notEmpty()->setName(trans('phone', [], 'message')))
            ->key('type', v::in([1, 2])->notEmpty()->setName(trans('type', [], 'message')))
            ->key('code', v::stringType()->setName(trans('code', [], 'message')), false)
            ->key('password', v::stringType()->setName(trans('password', [], 'message')), false);
        $data = $request->all();
        try {
            $validator->assert($data);
            //手机号规则
            if(!validateMalaysianPhoneNumber($data['phone'])){
                throw new Exception(trans('phone_val_error', [], 'message'));
            }
            $pattern = '/(\+60|60|0060)01\d{8,9}/';
            if (preg_match($pattern, $data['phone'])) {
                $data['phone'] = substr_replace($data['phone'], '601', 0, 4);
            }
            /** @var Player $player */
            $player = Player::where('phone', $data['phone'])
                ->where('department_id', request()->department_id)
                ->first();
            if(empty($player)){
                throw new Exception(trans('player_not_found', [], 'message'));
            }
            //密码登录
            if($data['type'] == 1){
                if(!isset($data['password']) || !password_verify($data['password'],$player->password)){
                    throw new Exception(trans('password_error', [], 'message'));
                }
            }else{
                //验证码错误
                $phone_code =  Redis::get(setSmsKey($data['phone'], PhoneSmsLog::TYPE_LOGIN));
                if(!$phone_code){
                    throw new Exception(trans('phone_sms_expire', [], 'message'));
                }
                if(!isset($data['code']) || empty($data['code']) || $phone_code != $data['code']){
                    throw new Exception(trans('phone_sms_error', [], 'message'));
                }
            }
            if ($player->status == Player::STATUS_STOP) {
                throw new Exception(trans('account_stop', [], 'message'));
            }
            $player->last_login = date('Y-m-d H:i:s');
            addLoginRecord($player->id);
        } catch (AllOfException $e) {
            throw new Exception(getValidationMessages($e));
        } catch (Exception $e) {
            throw new Exception($e->getMessage());
        }

        return jsonSuccessResponse('success', [
            'token' => JwtToken::generateToken([
                'id' => $player->id,
                'avatar' => $player->avatar,
                'name' => $player->name,
                'type' => $player->type,
                'currency' => $player->currency,
                'recommended_code' => $player->recommended_code,
            ]),
        ]);
    }

    /**
     * 手机号注册
     * @param Request $request
     * @return Response
     * @throws Exception
     */
    public function phoneRegister(Request $request): Response
    {
        $data = $request->all();
        $validator = v::key('phone', v::stringType()->notEmpty()->setName(trans('phone', [], 'message')))
            ->key('code', v::stringType()->setName(trans('code', [], 'message')))
            ->key('password', v::stringType()->setName(trans('password', [], 'message')))
            ->key('confim_password', v::stringType()->setName(trans('confim_password', [], 'message')))
            ->key('nickname', v::stringType()->setName(trans('nickname', [], 'message')));
        try {
            $validator->assert($data);
            //网页注册
            if(!empty($data['web_register']) && empty($data['recommended_code'])){
                throw new Exception(trans('recommend_player_not_found', [], 'message'));
            }
            //手机号规则
            if(!validateMalaysianPhoneNumber($data['phone'])){
                throw new Exception(trans('phone_val_error', [], 'message'));
            }
            $pattern = '/(\+60|60|0060)01\d{8,9}/';
            if (preg_match($pattern, $data['phone'])) {
                $data['phone'] = substr_replace($data['phone'], '601', 0, 4);
            }
            //两次密码不一致
            if($data['password'] != $data['confim_password']){
                throw new Exception(trans('confim_password_differ', [], 'message'));
            }
            //验证码错误
            $phone_code =  Redis::get(setSmsKey($data['phone'], PhoneSmsLog::TYPE_REGISTER));
            if(!$phone_code){
                throw new Exception(trans('phone_sms_expire', [], 'message'));
            }
            if(!isset($data['code']) || empty($data['code']) || $phone_code != $data['code']){
                throw new Exception(trans('phone_sms_error', [], 'message'));
            }
            /** @var Player $player */
            $player = Player::where('phone', $data['phone'])
                ->where('department_id', request()->department_id)
                ->first();
            //手机号已被注册
            if($player){
                throw new Exception(trans('phone_has_registered', [], 'message'));
            }
            $create_player['phone'] = $data['phone'];
            $create_player['password'] = $data['password'];
            $create_player['name'] = $data['nickname'];
            $player = createPlayer(request()->department_id,$create_player);
        } catch (AllOfException $e) {
            throw new Exception(getValidationMessages($e));
        } catch (Exception $e) {
            throw new Exception(trans('create_player_fail', [], 'message') . $e->getMessage());
        }
        return jsonSuccessResponse('success', [
            'token' => JwtToken::generateToken([
                'id' => $player->id,
                'avatar' => $player->avatar,
                'name' => $player->name,
                'type' => $player->type,
                'currency' => $player->currency,
                'recommended_code' => $player->recommended_code,
            ]),
        ]);
    }

    /**
     * 忘记密码
     * @param Request $request
     * @return Response
     * @throws \Exception
     */
    public function forgetPassword(Request $request): Response
    {
        $data = $request->all();
        $validator = v::key('phone', v::stringType()->notEmpty()->setName(trans('phone', [], 'message')))
            ->key('code', v::stringType()->setName(trans('code', [], 'message')))
            ->key('password', v::stringType()->setName(trans('password', [], 'message')))
            ->key('confim_password', v::stringType()->setName(trans('confim_password', [], 'message')));
        try {
            $validator->assert($data);
            //手机号规则
            if(!validateMalaysianPhoneNumber($data['phone'])){
                throw new Exception(trans('phone_val_error', [], 'message'));
            }
            $pattern = '/(\+60|60|0060)01\d{8,9}/';
            if (preg_match($pattern, $data['phone'])) {
                $data['phone'] = substr_replace($data['phone'], '601', 0, 4);
            }
            //两次密码不一致
            if($data['password'] != $data['confim_password']){
                throw new Exception(trans('confim_password_differ', [], 'message'));
            }
            //验证码错误
            $phone_code =  Redis::get(setSmsKey($data['phone'], PhoneSmsLog::TYPE_CHANGE_PASSWORD));
            if(!$phone_code){
                throw new Exception(trans('phone_sms_expire', [], 'message'));
            }
            if(!isset($data['code']) || empty($data['code']) || $phone_code != $data['code']){
                throw new Exception(trans('phone_sms_error', [], 'message'));
            }

            /** @var Player $player */
            $player = Player::where('phone', $data['phone'])
                ->where('department_id', request()->department_id)
                ->first();
            if(empty($player)){
                throw new Exception(trans('player_not_found', [], 'message'));
            }
            $player->password = $data['password'];
            $player->push();
        } catch (AllOfException $e) {
            throw new Exception(getValidationMessages($e));
        } catch (Exception $e) {
            throw new Exception($e->getMessage());
        }
        return jsonSuccessResponse(trans('password_revise_suc', [], 'message'));
    }

    /**
     * 发送验证码
     * @param Request $request
     * @return Response
     * @throws \Exception
     */
    public function sendMsg(Request $request): Response
    {
        $data = $request->all();
        $validator = v::key('phone', v::stringType()->notEmpty()->setName(trans('phone', [], 'message')))
        ->key('type', v::stringType()->setName(trans('type', [], 'message')), false);
        try {
            $validator->assert($data);
            //手机号规则
            if(!validateMalaysianPhoneNumber($data['phone'])){
                throw new Exception(trans('phone_val_error', [], 'message'));
            }
            $pattern = '/(\+60|60|0060)01\d{8,9}/';
            if (preg_match($pattern, $data['phone'])) {
                $data['phone'] = substr_replace($data['phone'], '601', 0, 4);
            }
            if ($data['type'] == 1 || $data['type'] == 3) {
                $player = Player::query()->where('phone', $data['phone'])->first();
                if(empty($player)){
                    throw new Exception(trans('player_not_found', [], 'message'));
                }
            }
            $env = config('app.env');
            $config = config('sms');
            $code = ($env == 'pro' ? random_int(10000, 99999) : config('sms.default_code'));
            //发送验证码
            $params = [
                    "userId" => $config['userId'],
                    "account"=> $config['account'],
                    "password"=> $config['password'],
                    "mobile"=> $data['phone'],
                    "content"=> '【Samsung88】您的验证码为'.$code.'，5分钟内有效。',
                    "sendTime"=> "",
                    "action"=> "sendhy",
                    "custom"=> "1"
            ];
            $result = doCurl($config['aliwy_url'], $params);
            if($result['code'] == 200 && $result['data']['status'] == 'Success'){
                $key = setSmsKey($data['phone'], $data['type']);
                $phoneSmsLog = new PhoneSmsLog();
                $phoneSmsLog->player_id = isset($data['player_id']) ? $data['player_id'] : 0;
                $phoneSmsLog->code = $code;
                $phoneSmsLog->phone = $data['phone'];
                $phoneSmsLog->send_times = 1;
                $phoneSmsLog->type = $data['type'];
                $phoneSmsLog->expire_time = date("Y-m-d H:i:s", time() + 300);
                $phoneSmsLog->response = $result ? json_encode($result) : '';
                Redis::set($key, $code, 'EX', 300);
                $phoneSmsLog->status = 1;
                $phoneSmsLog->save();
            }else{
                throw new Exception($result['data']['message']);
            }
        } catch (AllOfException $e) {
            throw new Exception(getValidationMessages($e));
        }catch (Exception $e) {
            throw new Exception($e->getMessage());
        }
        return jsonSuccessResponse(trans('phone_sms_send_success', [], 'message'));
    }

    /**
     * 获取用户信息
     * @param Request $request
     * @return Response
     * @throws GameException
     * @throws PlayerCheckException
     */
    public function playerInfo(Request $request): Response
    {
        $player = checkPlayer();

        $prizes = Prize::query()
            ->select('pic', 'name', 'id', 'type')
            ->where('department_id', $player->department_id)
            ->where('status', 1)
            ->orderBy('probability')
            ->get()
            ->toArray();
        $game = Game::query()->select('description', 'game_url')->first();
        return jsonSuccessResponse('success', [
            'id' => $player->id,
            'phone' => $player->phone,
            'avatar' => $player->avatar,
            'currency' => $player->currency,
            'uuid' => $player->uuid,
            'money' => $player->wallet->money,
            'name' => $player->name,
            'recharge_amount' => $player->player_extend->recharge_amount ?? 0,
            'game_description' => $game->description,
            'game_url' => $game->game_url,
            'prize_list' => $prizes,
            'bank_list' => PlayerBank::query()
                ->select('id', 'bank_name', 'account', 'account_name', 'bank_code')
                ->where('player_id', $player->id)
                ->where('status', 1)
                ->where('pay_type', '!=', 4)
                ->get(),
            'usdt' => PlayerBank::query()
                ->select('id', 'wallet_address', 'qr_code')
                ->where('player_id', $player->id)
                ->where('status', 1)
                ->where('pay_type', 4)
                ->first(),
            'whats_app' => Channel::query()->where('department_id', $player->department_id)->value('telegram_url'),
        ]);
    }

    /**
     * 获取充值列表
     * @return Response
     * @throws PlayerCheckException|GameException
     */
    public function rechargeList(): Response
    {
        $player = checkPlayer();
        $lang = locale();
        $lang = Str::replace('_', '-', $lang);
        $channelRechargeMethod = ChannelRechargeMethod::query()
            ->with(['methodLang' => function ($query) use ($lang) {
                $query->select(['id', 'bank_name', 'sub_bank', 'owner', 'name', 'method_id', 'lang'])->where('lang', $lang);
            }])
            ->where('status', 1)
            ->where('department_id', $player->department_id)
            ->orderBy('created_at', 'desc')
            ->select(['id', 'account', 'currency'])
            ->get();
        $list = [];
        /** @var ChannelRechargeMethod $item */
        foreach ($channelRechargeMethod as $item) {
            $list[] = [
                'id' => $item->id,
                'account' => $item->account,
                'currency' => $item->currency,
                'name' => $item->methodLang[0]['name'] ?? '',
                'bank_name' => $item->methodLang[0]['bank_name'] ?? '',
                'sub_bank' => $item->methodLang[0]['sub_bank'] ?? '',
                'owner' => $item->methodLang[0]['sub_bank'] ?? '',
            ];
        }

        return jsonSuccessResponse('success', [
            'list' => $list,
        ]);
    }

    /**
     * 获取充值项列表
     * @param Request $request
     * @return Response
     * @throws PlayerCheckException|GameException
     */
    public function rechargeSettingList(Request $request): Response
    {
        $player = checkPlayer();
        $data = $request->all();
        $validator = v::key('method_id', v::oneOf(v::intVal(), v::equals(''))->setName(trans('method_id', [], 'message')), false)
            ->key('setting_id', v::oneOf(v::intVal(), v::equals(''))->setName(trans('setting_id', [], 'message')), false)
            ->key('type', v::in([ChannelRechargeSetting::TYPE_REGULAR, ChannelRechargeSetting::TYPE_ACTIVITY, ''])->setName(trans('recharge_type', [], 'message')), false);
        try {
            $validator->assert($data);
        } catch (AllOfException $e) {
            return jsonFailResponse(getValidationMessages($e));
        }
        $list = ChannelRechargeSetting::query()
            ->whereHas('channel_recharge_method', function ($query) {
                $query->where('status', 1);
            })
            ->when(!empty($data['method_id']), function ($query) use ($data) {
                $query->where('method_id', $data['method_id']);
            })
            ->when(!empty($data['setting_id']), function ($query) use ($data) {
                $query->where('id', $data['setting_id']);
            })
            ->when(!empty($data['type']), function ($query) use ($data) {
                $query->where('type', $data['type']);
            })
            ->where('department_id', $player->department_id)
            ->where('status', 1)
            ->orderBy('coins_num', 'asc')
            ->select(['id', 'title', 'chip_multiple', 'coins_num', 'money', 'type', 'method_id'])
            ->get();

        return jsonSuccessResponse('success', [
            'list' => $list,
        ]);
    }

    /**
     * 充值详情
     * @param Request $request
     * @return Response
     * @throws PlayerCheckException|GameException
     */
    public function rechargeInfo(Request $request): Response
    {
        $player = checkPlayer();
        $data = $request->all();
        $validator = v::key('id', v::intVal()->notEmpty()->setName(trans('recharge_id', [], 'message')));
        try {
            $validator->assert($data);
        } catch (AllOfException $e) {
            return jsonFailResponse(getValidationMessages($e));
        }
        $lang = locale();
        $lang = Str::replace('_', '-', $lang);
        /** @var ChannelRechargeSetting $recharge */
        $recharge = ChannelRechargeSetting::query()
            ->with(['channel_recharge_method' => function ($query) use ($lang) {
                $query->select(['id', 'account', 'currency'])->with(['methodLang' => function ($query) use ($lang) {
                    $query->select(['id', 'bank_name', 'sub_bank', 'owner', 'name', 'method_id', 'lang'])->where('lang', $lang);
                }]);
            }])
            ->where('department_id', $player->department_id)
            ->where('id', $data['id'])
            ->select(['id', 'title', 'chip_multiple', 'coins_num', 'gift_coins', 'money', 'type', 'method_id', 'status'])
            ->first();

        if (!$recharge) {
            return jsonFailResponse(trans('recharge_setting_not_found', [], 'message'));
        }
        if ($recharge->status == 0) {
            return jsonFailResponse(trans('recharge_setting_disabled', [], 'message'));
        }

        return jsonSuccessResponse(trans('success', [], 'message'), [
            'recharge_setting' => $recharge
        ]);
    }

    /**
     * 编辑玩家名称
     * @param Request $request
     * @return Response
     * @throws PlayerCheckException|GameException
     */
    public function editPlayerName(Request $request): Response
    {
        $player = checkPlayer();
        $data = $request->all();
        $validator = v::key('player_name', v::stringVal()->length(1, 50)->setName(trans('player_name', [], 'message')));

        try {
            $validator->assert($data);
        } catch (AllOfException $e) {
            return jsonFailResponse(getValidationMessages($e));
        }
        if (Player::withTrashed()->where('name', $data['player_name'])->where('id', '!=', $player->id)->exists()) {
            return jsonFailResponse(trans('player_name_has_exist', [], 'message'));
        }
        $player->name = $data['player_name'] ?? '';
        $player->save();

        return jsonSuccessResponse('success');
    }

    /**
     * 數據中心
     * @return Response
     * @throws PlayerCheckException|GameException
     */
    public function giftCenter(): Response
    {
        $player = checkPlayer();

        return jsonSuccessResponse('success', [
            'chip_amount' => $player->chip_amount,
            'must_chip_amount' => $player->must_chip_amount,
            'coins' => $player->wallet->money,
        ]);
    }

    /**
     * 获取四方充值列表
     * @return Response
     * @throws PlayerCheckException|GameException
     */
    public function seRechargeList(): Response
    {
        $player = checkPlayer(false);
        $list = SepayRecharge::query()->where('department_id', $player->department_id)
            ->where('status', 1)
            ->orderBy('money')
            ->select(['id', 'title', 'coins_num', 'gift_coins', 'first_coins', 'money'])
            ->get()->toArray();
        $time = date('H:i:s');
        foreach ($list as &$value){
            $value['P2PDEPOSIT'] = 0;
            $value['DUITNOWP2P'] = 0;
            if ($value['money'] >= 5 && $value['money'] <= 1000) {
                $value['P2PDEPOSIT'] = 1;
                if ($time >= '23:50:00' || $time <= '01:05:00') {
                    $value['P2PDEPOSIT'] = 0;
                }
            }
            if ($value['money'] >= 30 && $value['money'] <= 20000) {
                $value['DUITNOWP2P'] = 1;
            }
            $firstRecharge = PlayerRechargeRecord::query()
                ->where('player_id', $player->id)
                ->where('status', 2)
                ->where('setting_id', $value['id'])
                ->first();
            if ($firstRecharge) {
                $value['first_coins'] = '0.00';
            }
        }
        unset($value);
        $bankList = [];
        $bankSelect = 0;

        if (in_array($player->channel->pay_type, [2, 3])) {
            $bankSelect = 1;
            $bankList = BankList::query()
                ->select(['bank_name', 'bank_code'])
                ->where('pay_type', $player->channel->pay_type)
                ->where('type', 1)
                ->whereNull('deleted_at')
                ->get()
                ->toArray();
        }
        $rechargeSetting = ChannelRechargeMethod::query()
            ->with('methodLang')
            ->select(['id', 'account', 'wallet_address', 'qr_code', 'type'])
            ->where('department_id', $player->department_id)
            ->where('status', 1)
            ->get()->toArray();
        foreach ($rechargeSetting as &$item) {
            if ($item['type'] == 1) {
                $item['name'] = 'artificial';
            } else {
                $item['name'] = 'usdt';
            }
        }
        unset($item);
        $rechargeSetting[] = [
            'name' => 'SKL',
            'type' => 3,
        ];
        return jsonSuccessResponse('success', [
            'list' => $list,
            'bank_select' => $bankSelect,
            'bank_list' => $bankList,
            'recharge_setting' => $rechargeSetting
        ]);
    }

    /**
     * 玩家充值
     * @param Request $request
     * @return Response
     * @throws PlayerCheckException
     * @throws GameException
     */
    public function seRecharge(Request $request): Response
    {
        $player = checkPlayer();
        $data = $request->all();
        $validator = v::key('amount', v::notEmpty()->intVal()->setName(trans('recharge_amount', [], 'message')))
            ->key('type', v::notEmpty()->intVal()->setName(trans('type', [], 'message')));

        try {
            $validator->assert($data);
        } catch (AllOfException $e) {
            return jsonFailResponse(getValidationMessages($e));
        }
        /** @var Channel $channel */
        $channel = Channel::where('department_id', $player->department_id)->first();
        if (empty($channel)) {
            return jsonFailResponse(trans('channel_not_found', [], 'message'));
        }
        /** @var SepayRecharge $sepayInfo */
        $sepayInfo = SepayRecharge::query()->where('department_id', $player->department_id)
            ->where('money', $data['amount'])->first();
        $firstCoins = 0;
        $allCoins = $data['amount'];
        if(!empty($sepayInfo)) {
            if ($sepayInfo->first_coins > 0) {
                $firstRecharge = PlayerRechargeRecord::query()
                    ->where('player_id', $player->id)
                    ->where('status', 2)
                    ->where('setting_id', $sepayInfo->id)
                    ->doesntExist();
                if ($firstRecharge) {
                    $firstCoins = $sepayInfo->first_coins;
                }
            }
            $allCoins = bcadd($sepayInfo->coins_num, $firstCoins, 2);
        }
        $orderNo = createOrderNo();
        // 生成充值订单
        $playerRechargeRecord = new  PlayerRechargeRecord();
        $playerRechargeRecord->player_id = $player->id;
        $playerRechargeRecord->department_id = $player->department_id;
        $playerRechargeRecord->tradeno = $orderNo;
        $playerRechargeRecord->player_name = $player->name ?? '';
        $playerRechargeRecord->money = $data['amount'];
        $playerRechargeRecord->inmoney = $data['amount'];
        $playerRechargeRecord->setting_id = $sepayInfo->id ?? 0;
        $playerRechargeRecord->coins = $data['amount'];
        $playerRechargeRecord->gift_coins = $firstCoins;
        $playerRechargeRecord->currency = 'RM';
        //手动支付
        if ($data['type'] == 1) {
            $playerRechargeRecord->type = PlayerRechargeRecord::TYPE_REGULAR;
            $playerRechargeRecord->status = PlayerRechargeRecord::STATUS_WAIT;
            $playerRechargeRecord->save();
        //USDT支付
        } elseif ($data['type'] == 2) {
            $rate = ChannelRechargeMethod::query()
                ->where('department_id', $player->department_id)
                ->where('type', 2)
                ->value('rate');
            $playerRechargeRecord->rate = $rate;
            $playerRechargeRecord->currency = 'USDT';
            $playerRechargeRecord->type = PlayerRechargeRecord::TYPE_REGULAR;
            $playerRechargeRecord->status = PlayerRechargeRecord::STATUS_WAIT;
            $playerRechargeRecord->save();
        //三方支付
        }elseif ($data['type'] == 3) {
            if ($data['payment_code'] == 'DUITNOWP2P') {
                $paymentCode = 'QR';
            } else {
                $paymentCode = $data['bank_code'];
            }
            $params = [
                'amount' => $data['amount'],
                'paymentCode' => $paymentCode,
                'name' => 'ggl-ds ' . $player->uuid,
                'orderNo' => $orderNo,
            ];
            $res = (new SklPayServices())->deposit($params);

            if (!isset($res['status']) && empty($res['code'])) {
                DB::beginTransaction();
                try {
                    $pay_url = $res['transaction_link'];
                    $playerRechargeRecord->payment_method = $params['paymentCode'] == 'QR' ? 'QR' : 'P2P';
                    $playerRechargeRecord->external_reference = $res['transaction_id'];
                    $playerRechargeRecord->type = PlayerRechargeRecord::TYPE_REGULAR;
                    $playerRechargeRecord->status = PlayerRechargeRecord::STATUS_WAIT;
                    $playerRechargeRecord->remark = 'SKL99';
                    $playerRechargeRecord->save();
                    DB::commit();
                } catch (\Exception $e) {
                    DB::rollBack();
                    return jsonFailResponse($e->getMessage());
                }
                return jsonSuccessResponse('success', ['pay_url' => $pay_url]);
            } else {
                return jsonFailResponse($res['error']);
            }
        }

        sendSocketMessage('private-admin_group-channel-' . request()->department_id, [
            'msg_type' => 'player_examine_recharge_order',
            'id' => $playerRechargeRecord->id,
            'player_id' => $player->id,
            'player_name' => $player->name,
            'player_phone' => $player->phone,
            'money' => $playerRechargeRecord->money,
            'status' => $playerRechargeRecord->status,
            'tradeno' => $playerRechargeRecord->tradeno,
        ]);

        $rechargeSetting = ChannelRechargeMethod::query()
            ->with('methodLang')
            ->select(['id', 'account', 'wallet_address', 'qr_code', 'type'])
            ->where('department_id', $player->department_id)
            ->where('status', 1)
            ->where('type', $data['type'])
            ->get()->toArray();
        return jsonSuccessResponse('success', [
            'tradeno' => $playerRechargeRecord->tradeno,
            'order_id' => $playerRechargeRecord->id,
            'money' => $playerRechargeRecord->money,
            'coins' => $allCoins,
            'currency' => $playerRechargeRecord->currency,
            'status' => $playerRechargeRecord->status,
            'created_at' => strtotime($playerRechargeRecord->created_at),
            'recharge_setting' => $rechargeSetting
        ]);
    }

    /**
     * 完成充值
     * @param Request $request
     * @return Response
     * @throws PlayerCheckException
     * @throws PushException|GameException
     */
    public function completeRecharge(Request $request): Response {
        $player = checkPlayer();
        $data = $request->post();
        $validator = v::key('id', v::notEmpty()->intVal()->setName(trans('recharge_record_id', [], 'message')))
            ->key('certificate', v::notEmpty()->stringVal()->setName(trans('certificate', [], 'message')));
        try {
            $validator->assert($data);
        } catch (AllOfException $e) {
            return jsonFailResponse(getValidationMessages($e));
        }
        /** @var PlayerRechargeRecord $rechargeRecord */
        $rechargeRecord = PlayerRechargeRecord::query()
            ->where('player_id', $player->id)
            ->where('id', $data['id'])
            ->first();
        if (empty($rechargeRecord)) {
            return jsonFailResponse(trans('recharge_record_not_found', [], 'message'));
        }
        switch ($rechargeRecord->status) {
            case PlayerRechargeRecord::STATUS_RECHARGING:
                return jsonFailResponse(trans('recharge_record_review_in_progress', [], 'message'));
            case PlayerRechargeRecord::STATUS_RECHARGED_SUCCESS:
                return jsonFailResponse(trans('recharge_completed', [], 'message'));
            case PlayerRechargeRecord::STATUS_RECHARGED_FAIL:
                return jsonFailResponse(trans('recharge_failed', [], 'message'));
            case PlayerRechargeRecord::STATUS_RECHARGED_CANCEL:
                return jsonFailResponse(trans('player_has_cancelled_recharge', [], 'message'));
            case PlayerRechargeRecord::STATUS_RECHARGED_REJECT:
                return jsonFailResponse(trans('recharge_order_review_failed', [], 'message'));
            case PlayerRechargeRecord::STATUS_RECHARGED_SYSTEM_CANCEL:
                return jsonFailResponse(trans('system_cancels_order', [], 'message'));
        }
        $rechargeRecord->status = PlayerRechargeRecord::STATUS_RECHARGING;
        $rechargeRecord->certificate = $data['certificate'];
        $rechargeRecord->save();

        sendSocketMessage('private-admin_group-channel-' . $player->department_id, [
            'msg_type' => 'player_examine_recharge_order',
            'id' => $rechargeRecord->id,
            'player_id' => $player->id,
            'player_name' => $player->name,
            'player_phone' => $player->phone,
            'money' => $rechargeRecord->money,
            'status' => $rechargeRecord->status,
            'tradeno' => $rechargeRecord->tradeno,
        ]);

        return jsonSuccessResponse('success');
    }

    /**
     * 玩家提现
     * @param Request $request
     * @return Response
     * @throws PlayerCheckException
     * @throws GameException
     */
    public function seWithdrawal(Request $request): Response
    {
        $player = checkPlayer();
        $data = $request->all();
        $validator = v::key('amount', v::intVal()->notEmpty()->min(100)->max(20000)->setName(trans('withdrawal_amount', [], 'message')))
            ->key('bank_id', v::intVal()->setName(trans('withdrawal_bank', [], 'message')))
            ->key('type', v::intVal()->setName(trans('type', [], 'message')));

        try {
            $validator->assert($data);
        } catch (AllOfException $e) {
            return jsonFailResponse(getValidationMessages($e));
        }

        /** @var Channel $channel */
        $channel = Channel::where('department_id', $player->department_id)->first();
        if ($player->status_withdraw != 1) {
            return jsonFailResponse(trans('player_withdraw_closed', [], 'message'));
        }
        if ($player->wallet->money < $data['amount']) {
            return jsonFailResponse(trans('insufficient_balance', [], 'message'));
        }
        if ($channel->withdraw_status == 0) {
            return jsonFailResponse(trans('self_withdraw_closed', [], 'message'));
        }
        if (empty($data['bank_id'])) {
            return jsonFailResponse(trans('please_select_player_bank', [], 'message'));
        }
        /** @var Currency $currency */
        $currency = Currency::where('identifying', $channel->currency)->where('status', 1)->whereNull('deleted_at')->first();
        if (empty($currency)) {
            return jsonFailResponse(trans('currency_no_setting', [], 'message'));
        }
        /** @var PlayerBank $playerBank */
        $playerBank = PlayerBank::where('id', $data['bank_id'])
            ->where('player_id', $player->id)
            ->where('status', 1)
            ->whereNull('deleted_at')
            ->first();
        if (empty($playerBank)) {
            return jsonFailResponse(trans('player_bank_not_found', [], 'message'));
        }
        //计算汇率
        $money = bcdiv($data['amount'], $currency->ratio, 2);
        //大于5000需要后台审核
        /*if ($money >= 5000) {
            DB::beginTransaction();
            try {
                $money = bcdiv($data['amount'], $currency->ratio, 2);
                // 生成订单
                $playerWithdrawRecord = new PlayerWithdrawRecord();
                $beforeGameAmount = $player->wallet->money;
                // 玩家钱包扣减
                $player->wallet->money = bcsub($player->wallet->money, $data['amount'], 2);
                $playerWithdrawRecord->player_id = $player->id;
                $playerWithdrawRecord->department_id = $player->department_id;
                $playerWithdrawRecord->tradeno = createOrderNo();
                $playerWithdrawRecord->player_name = $player->name ?? '';
                $playerWithdrawRecord->player_phone = $player->phone ?? '';
                $playerWithdrawRecord->money = $money;
                $playerWithdrawRecord->coins = $data['amount'];
                $playerWithdrawRecord->after_coins = $player->wallet->money;
                $playerWithdrawRecord->fee = 0;
                $playerWithdrawRecord->inmoney = bcsub($playerWithdrawRecord->money, $playerWithdrawRecord->fee, 2); // 实际提现金额
                $playerWithdrawRecord->currency = $channel->currency;
                $playerWithdrawRecord->bank_name = $playerBank->bank_name;
                $playerWithdrawRecord->bank_code = $playerBank->bank_code;
                $playerWithdrawRecord->account = $playerBank->account;
                $playerWithdrawRecord->account_name = $playerBank->account_name;
                $playerWithdrawRecord->type = PlayerWithdrawRecord::TYPE_SELF;
                $playerWithdrawRecord->status = PlayerWithdrawRecord::STATUS_WAIT;
                $playerWithdrawRecord->save();

                // 更新玩家统计
                $player->player_extend->withdraw_amount = bcadd($player->player_extend->withdraw_amount, $playerWithdrawRecord->coins, 2);
                $player->push();
                //寫入金流明細
                $playerDeliveryRecord = new PlayerDeliveryRecord;
                $playerDeliveryRecord->player_id = $playerWithdrawRecord->player_id;
                $playerDeliveryRecord->department_id = $playerWithdrawRecord->department_id;
                $playerDeliveryRecord->target = $playerWithdrawRecord->getTable();
                $playerDeliveryRecord->target_id = $playerWithdrawRecord->id;
                $playerDeliveryRecord->type = PlayerDeliveryRecord::TYPE_WITHDRAWAL;
                $playerDeliveryRecord->source = 'channel_withdrawal';
                $playerDeliveryRecord->amount = $playerWithdrawRecord->coins;
                $playerDeliveryRecord->amount_before = $beforeGameAmount;
                $playerDeliveryRecord->amount_after = $player->wallet->money;
                $playerDeliveryRecord->tradeno = $playerWithdrawRecord->tradeno ?? '';
                $playerDeliveryRecord->remark = $playerWithdrawRecord->remark ?? '';
                $playerDeliveryRecord->save();
                DB::commit();
            } catch (\Exception $e) {
                DB::rollBack();
                return jsonFailResponse(trans('system_error', [], 'message') . $e->getMessage());
            }

            $notice = new Notice();
            $notice->department_id = $playerWithdrawRecord->department_id;
            $notice->player_id = $playerWithdrawRecord->player_id;
            $notice->source_id = $playerWithdrawRecord->id;
            $notice->type = Notice::TYPE_EXAMINE_WITHDRAW;
            $notice->receiver = Notice::RECEIVER_DEPARTMENT;
            $notice->is_private = 0;
            $notice->title = '渠道提现待审核';
            $notice->content = '提现订单待审核,玩家' . (empty($playerWithdrawRecord->player_name) ? $playerWithdrawRecord->player_name : $playerWithdrawRecord->player_phone) . ', 提现游戏点: ' . $playerWithdrawRecord->point . ' 提现金额: ' . $playerWithdrawRecord->money;
            $notice->save();

            if ($playerWithdrawRecord->status == PlayerWithdrawRecord::STATUS_FAIL) {
                return jsonFailResponse(trans('withdraw_fail', [], 'message'));
            }
            sendSocketMessage('private-admin_group-channel-' . $channel->department_id, [
                'msg_type' => 'player_create_withdraw_order',
                'id' => $playerWithdrawRecord->id,
                'player_id' => $player->id,
                'player_name' => $player->name,
                'player_phone' => $player->phone,
                'money' => $playerWithdrawRecord->money,
                'status' => $playerWithdrawRecord->status,
                'tradeno' => $playerWithdrawRecord->tradeno,
            ]);
            return jsonSuccessResponse('success', [
                'tradeno' => $playerWithdrawRecord->tradeno,
                'order_id' => $playerWithdrawRecord->id,
                'money' => $playerWithdrawRecord->money,
                'currency' => $playerWithdrawRecord->currency,
                'status' => $playerWithdrawRecord->status,
            ]);
        }*/

        // 生成订单
        $orderNo = createOrderNo();
        $playerWithdrawRecord = new PlayerWithdrawRecord();
        $beforeGameAmount = $player->wallet->money;
        // 玩家钱包扣减
        $player->wallet->money = bcsub($player->wallet->money, $data['amount'], 2);
        $playerWithdrawRecord->player_id = $player->id;
        $playerWithdrawRecord->department_id = $player->department_id;
        $playerWithdrawRecord->tradeno = $orderNo;
        $playerWithdrawRecord->player_name = $player->name ?? '';
        $playerWithdrawRecord->player_phone = $player->phone ?? '';
        $playerWithdrawRecord->money = $money;
        $playerWithdrawRecord->coins = $data['amount'];
        $playerWithdrawRecord->after_coins = $player->wallet->money;
        $playerWithdrawRecord->fee = 0;
        $playerWithdrawRecord->inmoney = bcsub($playerWithdrawRecord->money, $playerWithdrawRecord->fee, 2); // 实际提现金额
        $playerWithdrawRecord->currency = $channel->currency;

        DB::beginTransaction();
        try {
            //银行卡提现
            if ($data['type'] == 1) {
                $playerWithdrawRecord->bank_name = $playerBank->bank_name;
                $playerWithdrawRecord->bank_code = $playerBank->bank_code;
                $playerWithdrawRecord->account = $playerBank->account;
                $playerWithdrawRecord->account_name = $playerBank->account_name;
                $playerWithdrawRecord->type = PlayerWithdrawRecord::TYPE_SELF;
                $playerWithdrawRecord->status = PlayerWithdrawRecord::STATUS_WAIT;
                $playerWithdrawRecord->save();
            //USDT提现
            } elseif ($data['type'] == 2) {
                $rate = ChannelRechargeMethod::query()
                    ->where('department_id', $player->department_id)
                    ->where('type', 2)
                    ->value('rate');
                $playerWithdrawRecord->rate = $rate;
                $playerWithdrawRecord->currency = 'USDT';
                $playerWithdrawRecord->wallet_address = $playerBank->wallet_address;
                $playerWithdrawRecord->qr_code = $playerBank->qr_code;
                $playerWithdrawRecord->type = PlayerWithdrawRecord::TYPE_USDT;
                $playerWithdrawRecord->status = PlayerWithdrawRecord::STATUS_WAIT;
                $playerWithdrawRecord->save();
            //三方提现
            } else {
                $params = [
                    'amount' => $money,
                    'bankCode' => $playerBank->bank_code,
                    'bankAccountNo' => $playerBank->account,
                    'bankAccountName' => $playerBank->account_name,
                    'orderNo' => $orderNo,
                ];
                $res = (new SklPayServices())->payout($params);
                if ($res['code'] == 'success') {
                        $playerWithdrawRecord->bank_name = $playerBank->bank_name;
                        $playerWithdrawRecord->bank_code = $playerBank->bank_code;
                        $playerWithdrawRecord->account = $playerBank->account;
                        $playerWithdrawRecord->account_name = $playerBank->account_name;
                        $playerWithdrawRecord->talk_tradeno = $res['data']['reference_number'];
                        $playerWithdrawRecord->type = PlayerWithdrawRecord::TYPE_SKLPAYOUT;
                        $playerWithdrawRecord->status = PlayerWithdrawRecord::STATUS_WAIT;
                        $playerWithdrawRecord->save();
                } else {
                    return jsonFailResponse($res['error']);
                }
            }
            DB::commit();
        } catch (\Exception $e) {
            DB::rollBack();
            return jsonFailResponse(trans('system_error', [], 'message') . $e->getMessage());
        }

        // 更新玩家统计
        $player->player_extend->withdraw_amount = bcadd($player->player_extend->withdraw_amount, $playerWithdrawRecord->coins, 2);
        $player->push();

        //寫入金流明細
        $playerDeliveryRecord = new PlayerDeliveryRecord;
        $playerDeliveryRecord->player_id = $playerWithdrawRecord->player_id;
        $playerDeliveryRecord->department_id = $playerWithdrawRecord->department_id;
        $playerDeliveryRecord->target = $playerWithdrawRecord->getTable();
        $playerDeliveryRecord->target_id = $playerWithdrawRecord->id;
        $playerDeliveryRecord->type = PlayerDeliveryRecord::TYPE_WITHDRAWAL;
        $playerDeliveryRecord->source = 'channel_withdrawal';
        $playerDeliveryRecord->amount = $playerWithdrawRecord->coins;
        $playerDeliveryRecord->amount_before = $beforeGameAmount;
        $playerDeliveryRecord->amount_after = $player->wallet->money;
        $playerDeliveryRecord->tradeno = $playerWithdrawRecord->tradeno ?? '';
        $playerDeliveryRecord->remark = '';
        $playerDeliveryRecord->save();

        return jsonSuccessResponse('success', [
            'tradeno' => $playerWithdrawRecord->tradeno,
            'money' => $playerWithdrawRecord->money,
            'currency' => $playerWithdrawRecord->currency,
            'status' => $playerWithdrawRecord->status,
        ]);
    }


    /**
     * 玩家账变记录
     * @param Request $request
     * @return Response
     * @throws PlayerCheckException|PromoterCheckException
     */
    public function playerDeliveryRecord(Request $request): Response
    {
        $player = checkPlayer(false);
        $validator = v::key('page', v::intVal()->setName(trans('page', [], 'message')))
            ->key('type', v::stringVal()->setName(trans('date_type', [], 'message')))
            ->key('size', v::intVal()->setName(trans('size', [], 'message')));
        $data = $request->all();
        try {
            $validator->assert($data);
        } catch (AllOfException $e) {
            return jsonFailResponse(getValidationMessages($e));
        }
        try {
            $playerDeliveryRecordModel = PlayerDeliveryRecord::where('player_id', $player->id);
            switch ($data['type']) {
                case 'today': // 今天
                    $playerDeliveryRecordModel->whereDate('created_at', date('Y-m-d'));
                    break;
                case 'week': // 本周
                    $playerDeliveryRecordModel->where('created_at', '>=', \Carbon\Carbon::today()->startOfWeek())->where('created_at', '<=', Carbon::today()->endOfWeek());
                    break;
                case 'month': // 本月
                    $playerDeliveryRecordModel->where('created_at', '>=', Carbon::today()->firstOfMonth())->where('created_at', '<=', Carbon::today()->endOfMonth());
                    break;
                case 'sub_month': // 上月
                    $playerDeliveryRecordModel->where('created_at', '>=', Carbon::today()->subMonth()->firstOfMonth())->where('created_at', '<=', Carbon::today()->subMonth()->endOfMonth());
                    break;
                default:
                    $playerDeliveryRecordModel->whereDate('created_at', date('Y-m-d'));
                    break;
            }
            $inType = implode(',', [
                PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_ADD,
                PlayerDeliveryRecord::TYPE_PRESENT_IN,
                PlayerDeliveryRecord::TYPE_GAME_IN,
                PlayerDeliveryRecord::TYPE_ACTIVITY_BONUS,
                PlayerDeliveryRecord::TYPE_REGISTER_PRESENT,
                PlayerDeliveryRecord::TYPE_PROFIT,
                PlayerDeliveryRecord::TYPE_LOTTERY,
            ]);
            $outType = implode(',', [
                PlayerDeliveryRecord::TYPE_PRESENT_OUT,
                PlayerDeliveryRecord::TYPE_GAME_OUT,
                PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_DEDUCT,
            ]);
            $totalModel = clone $playerDeliveryRecordModel;
            $totalData = $totalModel->selectRaw('sum(IF(type in (' . $inType . '), amount, 0)) as total_in, sum(IF(type in (' . $outType . '), amount, 0)) as total_out, sum(IF(type = ' . PlayerDeliveryRecord::TYPE_WITHDRAWAL . ', amount, 0)) as total_withdrawal, sum(IF(type = ' . PlayerDeliveryRecord::TYPE_WITHDRAWAL_BACK . ', amount, 0)) as total_withdrawal_back, sum(IF(type = ' . PlayerDeliveryRecord::TYPE_RECHARGE . ', amount, 0)) as total_recharge')->first();

            $playerDeliveryRecord = $playerDeliveryRecordModel->forPage($data['page'], $data['size'])
                ->orderBy('id', 'desc')
                ->get();
            $list = [];
            /** @var PlayerDeliveryRecord $item */
            foreach ($playerDeliveryRecord as $item) {
                switch ($item->type) {
                    case PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_ADD:
                        $item->target = trans('target.modified_amount_add', [], 'message');
                        break;
                    case PlayerDeliveryRecord::TYPE_PRESENT_IN:
                        $item->target = trans('target.present_in', [], 'message');
                        break;
                    case PlayerDeliveryRecord::TYPE_PRESENT_OUT:
                        $item->target = trans('target.present_out', [], 'message');
                        $item->amount = '-' . $item->amount;
                        break;
                    case PlayerDeliveryRecord::TYPE_GAME_OUT:
                        $item->target = trans('target.machine_up', [], 'message');
                        $item->amount = '-' . $item->amount;
                        break;
                    case PlayerDeliveryRecord::TYPE_GAME_IN:
                        $item->target = trans('target.machine_down', [], 'message');
                        break;
                    case PlayerDeliveryRecord::TYPE_RECHARGE:
                        switch ($item->source) {
                            case 'artificial_recharge':
                                $item->target = trans('target.artificial_recharge', [], 'message');
                                break;
                            case 'self_recharge':
                                $item->target = trans('target.self_recharge', [], 'message');
                                break;
                            case 'talk_recharge':
                                $item->target = trans('target.talk_recharge', [], 'message');
                                break;
                            case 'coin_recharge':
                                $item->target = trans('target.coin_recharge', [], 'message');
                                break;
                        }
                        break;
                    case PlayerDeliveryRecord::TYPE_WITHDRAWAL:
                        switch ($item['source']) {
                            case 'artificial_withdrawal':
                                $item->target = trans('target.artificial_withdrawal', [], 'message');
                                break;
                            case 'talk_withdrawal':
                                $item->target = trans('target.talk_withdrawal', [], 'message');
                                break;
                            case 'channel_withdrawal':
                                $item->target = trans('target.channel_withdrawal', [], 'message');
                                break;
                        }
                        $item->amount = '-' . $item->amount;
                        break;
                    case PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_DEDUCT:
                        $item->target = trans('target.modified_amount_deduct', [], 'message');
                        $item->amount = '-' . $item->amount;
                        break;
                    case PlayerDeliveryRecord::TYPE_WITHDRAWAL_BACK:
                        $item->target = trans('target.withdrawal_back', [], 'message');
                        break;
                    case PlayerDeliveryRecord::TYPE_ACTIVITY_BONUS:
                        $item->target = trans('target.activity_bonus', [], 'message');
                        break;
                    case PlayerDeliveryRecord::TYPE_REGISTER_PRESENT:
                        $item->target = trans('target.register_present', [], 'message');
                        break;
                    case PlayerDeliveryRecord::TYPE_PROFIT:
                        $item->target = trans('target.profit', [], 'message');
                        break;
                    default:
                        break;
                }
                $list[] = [
                    'id' => $item->id,
                    'amount' => $item->amount,
                    'source' => $item->target,
                    'amount_after' => $item->amount_after,
                    'created_at' => date('Y-m-d H:i:s', strtotime($item->created_at)),
                ];
            }
        } catch (\Exception $e) {
            return jsonFailResponse($e->getMessage());
        }

        return jsonSuccessResponse('success', [
            'list' => $list,
            'player' => [
                'uuid' => $player->uuid,
                'name' => $player->name,
                'promoter_uuid' => $player->uuid,
            ],
            'total_data' => [
                'total_in' => $totalData['total_in'] ?? 0,
                'total_out' => $totalData['total_out'] ?? 0,
                'total_withdrawal' => bcsub($totalData['total_withdrawal'] ?? 0, $totalData['total_withdrawal_back'] ?? 0, 2),
                'total_recharge' => $totalData['total_recharge'] ?? 0,
            ],
            'date_type' => [
                'today' => Carbon::today()->format('Y-m-d'),
                'week' => Carbon::today()->startOfWeek()->format('Y-m-d') . '~' . Carbon::today()->endOfWeek()->format('Y-m-d'),
                'month' => Carbon::today()->firstOfMonth()->format('Y-m-d') . '~' . Carbon::today()->endOfMonth()->format('Y-m-d'),
                'sub_month' => Carbon::today()->subMonth()->firstOfMonth()->format('Y-m-d') . '~' . Carbon::today()->subMonth()->endOfMonth()->format('Y-m-d'),
            ]
        ]);
    }

    /**
     * 游戏记录
     * @param Request $request
     * @return Response
     * @throws PlayerCheckException|GameException
     */
    public function gameRecord(Request $request): Response
    {
        $player = checkPlayer();
        $data = $request->all();
        $validator = v::key('page', v::intVal()->setName(trans('page', [], 'message')))
            ->key('size', v::intVal()->setName(trans('size', [], 'message')));

        try {
            $validator->assert($data);
        } catch (AllOfException $e) {
            return jsonFailResponse(getValidationMessages($e));
        }

        $records = DrawRecord::query()
            ->select('prize_pic', 'prize_name', 'prize_type', 'draw_time', 'ip')
            ->where('uid', $player->id)
            ->orderBy('id', 'desc')
            ->forPage($data['page'], $data['size'])
            ->get()
            ->toArray();
        return jsonSuccessResponse('success', $records);
    }

    /**
     * 充提记录
     * @param Request $request
     * @return Response
     * @throws PlayerCheckException|GameException
     */
    public function depositWithdrawalRecord(Request $request): Response
    {
        $player = checkPlayer();
        $data = $request->all();
        $validator = v::key('page', v::intVal()->setName(trans('page', [], 'message')))
            ->key('size', v::intVal()->setName(trans('size', [], 'message')))
            ->key('type', v::intVal()->setName(trans('type', [], 'message')))
            ->key('start_date', v::stringVal()->setName(trans('start_date', [], 'message')))
            ->key('end_date', v::stringVal()->setName(trans('end_date', [], 'message')));

        try {
            $validator->assert($data);
        } catch (AllOfException $e) {
            return jsonFailResponse(getValidationMessages($e));
        }
        // 1. 构建充值查询
        $rechargeQuery = DB::table('player_recharge_record')
            ->select('money', 'created_at', 'status', DB::raw("1 as type"))
            ->where('player_id', $player->id)
            ->whereBetween('created_at', [$data['start_date'],date('Y-m-d', strtotime("{$data['end_date']} +1 days"))]);

        // 2. 构建提现查询
        $withdrawQuery = DB::table('player_withdraw_record')
            ->select('money', 'created_at', 'status', DB::raw("2 as type"))
            ->where('player_id', $player->id)
            ->whereBetween('created_at', [$data['start_date'],date('Y-m-d', strtotime("{$data['end_date']} +1 days"))]);
        // 3. 根据类型参数过滤
        if ($data['type'] == 1) {
            $query = $rechargeQuery;
        } elseif ($data['type'] == 2) {
            $query = $withdrawQuery;
        } else {
            $query = $rechargeQuery->unionAll($withdrawQuery);
        }
        // 4. 处理排序和分页
        $records = DB::table(DB::raw("({$query->toSql()}) as combined_transactions"))
            ->mergeBindings($query) // 重要：合并 SQL 绑定参数
            ->orderBy('created_at', 'desc')
            ->forPage($data['page'], $data['size'])
            ->get()->toArray();
        return jsonSuccessResponse('success', $records);
    }
}
