<?php

namespace addons\webman\controller;

use addons\webman\Admin;
use addons\webman\model\Channel;
use addons\webman\model\PhoneSmsLog;
use addons\webman\model\Player;
use addons\webman\model\PlayerBank;
use addons\webman\model\PlayerChipRecord;
use addons\webman\model\PlayerDeliveryRecord;
use addons\webman\model\PlayerExtend;
use addons\webman\model\PlayerMoneyEditLog;
use addons\webman\model\PlayerPlatformCash;
use addons\webman\model\PlayerRechargeRecord;
use addons\webman\model\PlayerRegisterRecord;
use addons\webman\model\PlayerTag;
use addons\webman\model\PlayerWithdrawRecord;
use ExAdmin\ui\component\common\Button;
use ExAdmin\ui\component\common\Html;
use ExAdmin\ui\component\common\Icon;
use ExAdmin\ui\component\form\Form;
use ExAdmin\ui\component\grid\avatar\Avatar;
use ExAdmin\ui\component\grid\card\Card;
use ExAdmin\ui\component\grid\grid\Actions;
use ExAdmin\ui\component\grid\grid\Editable;
use ExAdmin\ui\component\grid\grid\Filter;
use ExAdmin\ui\component\grid\grid\Grid;
use ExAdmin\ui\component\grid\statistic\Statistic;
use ExAdmin\ui\component\grid\tabs\Tabs;
use ExAdmin\ui\component\grid\tag\Tag;
use ExAdmin\ui\component\grid\ToolTip;
use ExAdmin\ui\component\layout\layout\Layout;
use ExAdmin\ui\component\layout\Row;
use ExAdmin\ui\response\Msg;
use ExAdmin\ui\response\Response;
use ExAdmin\ui\support\Container;
use ExAdmin\ui\support\Request;
use Exception;
use Illuminate\Validation\Rule;
use support\Cache;
use support\Db;
use addons\webman\model\PlayerPromoter;
use Illuminate\Support\Str;

/**
 * 渠道玩家
 * @group channel
 */
class ChannelPlayerController
{
    protected $model;

    protected $playerTag;

    private $withdraw;

    private $recharge;

    private $promoter;

    private $playerChipRecord;

    protected $playerActivityPhaseRecord;

    protected $playerLotteryRecord;

    protected $playerDeliveryRecord;

    public function __construct()
    {
        $this->model = plugin()->webman->config('database.player_model');
        $this->playerTag = plugin()->webman->config('database.player_tag_model');
        $this->withdraw = plugin()->webman->config('database.player_withdraw_record_model');
        $this->recharge = plugin()->webman->config('database.player_recharge_record_model');
        $this->promoter = plugin()->webman->config('database.player_promoter_model');
        $this->playerChipRecord = plugin()->webman->config('database.player_chip_record_model');
        $this->playerActivityPhaseRecord = plugin()->webman->config('database.player_activity_phase_record_model');
        $this->playerLotteryRecord = plugin()->webman->config('database.player_lottery_record_model');
        $this->playerDeliveryRecord = plugin()->webman->config('database.player_delivery_record_model');
    }

    /**
     * 渠道玩家
     * @auth true
     * @group channel
     * @return Grid
     */
    public function index(): Grid
    {
        /** @var Channel $channel */
        $channel = Channel::where('department_id', Admin::user()->department_id)->first();
        return Grid::create(new $this->model(), function (Grid $grid) use ($channel) {
            $grid->title(admin_trans('player.title'));
            $requestFilter = Request::input('ex_admin_filter', []);
            if (isset($requestFilter['search_type']) && !empty($requestFilter['search_type'])) {
                $grid->model()->where('is_coin', $requestFilter['search_type']);
            }
            if (isset($requestFilter['created_at_start']) && !empty($requestFilter['created_at_start'])) {
                $grid->model()->where('player.created_at', '>=', $requestFilter['created_at_start']);
            }
            if (isset($requestFilter['created_at_end']) && !empty($requestFilter['created_at_end'])) {
                $grid->model()->where('player.created_at', '<=', $requestFilter['created_at_end']);
            }
            $activePlayer = Request::input('active_player') ?? null;
            if (!empty($activePlayer)){
                $grid->model()->whereHas('the_last_player_login_record', function ($query) use ($activePlayer) {
                    if ($activePlayer == 1){
                        $query->whereDate('created_at', date('Y-m-d'));
                    } else {
                        $query->whereYear('created_at', date('Y'))
                            ->whereMonth('created_at', date('m'));
                    }
                });
            }
            $subQuery = PlayerDeliveryRecord::select('player_id', Db::raw('sum(amount) as amount'))
                ->whereNotIn('type', [1,2,3,4,5,9,10])
                ->groupBy('player_id');
            $grid->model()->with(['player_register_record', 'the_last_player_login_record'])
                ->select([
                    'player.*',
                    'player_extend.recharge_amount',
                    'player_extend.withdraw_amount',
                    'player_platform_cash.money as money',
                    'record.amount as present_coins'
                ])
                ->leftjoin('player_extend', 'player.id', '=', 'player_extend.player_id')
                ->leftjoin('player_platform_cash', 'player.id', '=', 'player_platform_cash.player_id')
                ->leftjoinSub($subQuery, 'record', function ($join) {
                    $join->on('player.id', '=', 'record.player_id');
                })
                ->orderBy('player.id', 'desc');
            $grid->autoHeight();
            $grid->bordered();
            $grid->column('id', admin_trans('player.fields.id'))->fixed(true)->align('center');
            $grid->column('name', admin_trans('player.fields.name'))->display(function ($val, Player $data) {
                $image = $data->avatar ? Avatar::create()->src(is_numeric($data->avatar) ? config('def_avatar.' . $data->avatar) : $data->avatar) : Avatar::create()->icon(Icon::create('UserOutlined'));
                return Html::create()->content([
                    $image,
                    Html::div()->content($val),
                ]);
            })->fixed(true)->align('center');
            $grid->column('uuid', admin_trans('player.fields.uuid'))->fixed(true)->ellipsis(true)->align('center');
            $grid->column('phone', admin_trans('player.fields.phone'))->fixed(true)->ellipsis(true)->align('center');
            $grid->column('money', admin_trans('player_platform_cash.platform_name.' . PlayerPlatformCash::PLATFORM_SELF))->display(function ($val, Player $data) {
                return Tag::create($val)->color('orange')->style(['cursor' => 'pointer'])->modal([$this, 'playerRecord'], ['id' => $data->id])->width('70%')->title($data->name . ' ' . $data->uuid);
            })->ellipsis(true)->align('center')->sortable();
            $grid->column('player_extend.recharge_amount', admin_trans('player_extend.fields.recharge_amount'))->ellipsis(true)->align('center')->sortable();
            $grid->column('player_extend.withdraw_amount', admin_trans('player_extend.fields.withdraw_amount'))->ellipsis(true)->align('center')->sortable();
            $grid->column('status', admin_trans('player.fields.status'))->switch()->ellipsis(true)->align('center');
            $grid->column('player.created_at', admin_trans('player.fields.created_at'))->display(function ($val, Player $data) {
                return Html::create()->content([
                    Html::div()->content(date('Y-m-d H:i:s', strtotime($data->created_at))),
                    Html::div()->content($data->player_register_record->ip ?? ''),
                    Html::div()->content($data->player_register_record->country_name ?? ''),
                ]);
            })->ellipsis(true)->align('center')->sortable();
            $grid->column('last_login', admin_trans('player.fields.player_login_record'))->display(function ($val, Player $data) {
                return Html::create()->content([
                    Html::div()->content($val ?? (!empty($data->the_last_player_login_record->created_at) ? date('Y-m-d H:i:s', strtotime($data->the_last_player_login_record->created_at)) : '')),
                    Html::div()->content($data->the_last_player_login_record->ip ?? ''),
                    Html::div()->content($data->the_last_player_login_record->country_name ?? ''),
                ]);
            })->ellipsis(true)->align('center')->sortable();
            $grid->filter(function (Filter $filter) use ($channel) {
                $filter->like()->text('uuid')->placeholder(admin_trans('player.fields.uuid'));
                $filter->like()->text('name')->placeholder(admin_trans('player.fields.name'));
                $filter->like()->text('phone')->placeholder(admin_trans('player.fields.phone'));
                $filter->eq()->select('level')
                    ->showSearch()
                    ->style(['width' => '200px'])
                    ->dropdownMatchSelectWidth()
                    ->placeholder(admin_trans('player.fields.level'))
                    ->options(playerLevelOptions());
                $filter->form()->hidden('created_at_start');
                $filter->form()->hidden('created_at_end');
                $filter->form()->dateTimeRange('created_at_start', 'created_at_end', '')->placeholder([admin_trans('public_msg.created_at_start'), admin_trans('public_msg.created_at_end')]);
            });
            $grid->expandFilter();
            $grid->hideDelete();
            $grid->hideSelection();
            $grid->tools(
                $grid->addButton()->modal($this->form())
            );
            $grid->actions(function (Actions $actions, Player $data) use ($channel) {
                $actions->edit()->modal($this->form())->width('60%');
                $actions->hideDel();
                $dropdown = $actions->dropdown();
                if ($channel->wallet_action_status == 1) {
                    $dropdown->append(admin_trans('player.wallet.player_wallet'), 'MoneyCollectFilled')
                        ->modal($this->playerWallet([
                            'id' => $data->id,
                            'money' => $data->wallet->money ?? 0,
                        ]))->width('600px');
                }
                $dropdown->append(admin_trans('player.wallet.artificial_recharge'), 'TransactionOutlined')
                    ->modal($this->artificialRecharge([
                        'id' => $data->id,
                        'money' => $data->wallet->money ?? 0,
                    ]))->width('600px')->title(Html::create(admin_trans('player.wallet.artificial_recharge'))->content(
                        ToolTip::create(Icon::create('QuestionCircleOutlined')->style(['marginLeft' => '5px', 'cursor' => 'pointer']))->title(admin_trans('player.wallet.artificial_recharge_tip'))
                    ));
                $dropdown->append(admin_trans('player.wallet.artificial_withdrawal'), 'PayCircleOutlined')
                    ->modal($this->artificialWithdrawal([
                        'id' => $data->id,
                        'money' => $data->wallet->money ?? 0,
                    ]))->width('600px')->title(Html::create(admin_trans('player.wallet.artificial_withdrawal'))->content(
                        ToolTip::create(Icon::create('QuestionCircleOutlined')->style(['marginLeft' => '5px', 'cursor' => 'pointer']))->title(admin_trans('player.wallet.artificial_withdrawal_tip'))
                    ));
            });
            $grid->tools([
                ToolTip::create(Icon::create('QuestionCircleOutlined')->style(['margin-left' => '10px', 'margin-top' => '4px', 'line-height' => '28px', 'font-size' => '15px', 'cursor' => 'pointer']))->title(admin_trans('player.set_promoter_tip'))
            ]);
            $grid->updateing(function ($ids, $data) {
                if (isset($ids[0]) && isset($data['player_extend'])) {
                    if (PlayerExtend::updateOrCreate(
                        ['player_id' => $ids[0]],
                        $data['player_extend']
                    )) {
                        return message_success(admin_trans('player.remark_edit_success'));
                    }
                }
            });
        });
    }

    /**
     * 人工提现
     * @auth true
     * @group channel
     * @param $data
     * @return Form
     */
    public function artificialWithdrawal($data): Form
    {
        return Form::create(new $this->model, function (Form $form) use ($data) {
            $form->number('coins', admin_trans('player_withdraw_record.fields.coins'))
                ->min(0)
                ->max(100000000)
                ->precision(2)
                ->style(['width' => '100%'])
                ->addonBefore(admin_trans('player.wallet.wallet') . ' ' . $data['money'] ?? 0)
                ->required();
            $form->number('money', admin_trans('player_withdraw_record.fields.money'))
                ->min(0)
                ->max(100000000)
                ->precision(2)
                ->style(['width' => '100%']);
            $form->text('currency', admin_trans('player_withdraw_record.fields.currency'))->maxlength(10);
            $form->text('bank_name', admin_trans('player_withdraw_record.fields.bank_name'))->maxlength(50);
            $form->text('account', admin_trans('player_withdraw_record.fields.account'))->maxlength(50);
            $form->text('account_name', admin_trans('player_withdraw_record.fields.account_name'))->maxlength(50);
            $form->textarea('remark', admin_trans('player_withdraw_record.fields.remark'))->maxlength(255)->bindAttr('rows', 4);
            $form->layout('vertical');
            $form->hidden('id')->value($data['id']);
            $form->saving(function (Form $form) {
                /** @var Player $player */
                $player = Player::where('id', $form->input('id'))->whereNull('deleted_at')->first();
                if (empty($player)) {
                    return message_error(admin_trans('player.not_fount'));
                }
                if ($player->status == 0) {
                    return message_error(admin_trans('player.disable'));
                }
                if ($player->wallet->money < $form->input('coins')) {
                    return message_error(admin_trans('player.insufficient_balance'));
                }
                DB::beginTransaction();
                try {
                    // 生成订单
                    $playerWithdrawRecord = new PlayerWithdrawRecord();
                    $playerWithdrawRecord->player_id = $player->id;
                    $playerWithdrawRecord->talk_user_id = $player->talk_user_id;
                    $playerWithdrawRecord->department_id = $player->department_id;
                    $playerWithdrawRecord->tradeno = createOrderNo();
                    $playerWithdrawRecord->player_name = $player->name ?? '';
                    $playerWithdrawRecord->player_phone = $player->phone ?? '';
                    $playerWithdrawRecord->money = $form->input('money') ?? 0;
                    $playerWithdrawRecord->coins = $form->input('coins') ?? 0;
                    $playerWithdrawRecord->fee = 0;
                    $playerWithdrawRecord->inmoney = bcsub($playerWithdrawRecord->money, $playerWithdrawRecord->fee, 2); // 实际提现金额
                    $playerWithdrawRecord->currency = $form->input('currency') ?? 0;
                    $playerWithdrawRecord->bank_name = $form->input('bank_name') ?? 0;
                    $playerWithdrawRecord->account = $form->input('account') ?? 0;
                    $playerWithdrawRecord->account_name = $form->input('account_name') ?? 0;
                    $playerWithdrawRecord->type = PlayerWithdrawRecord::TYPE_ARTIFICIAL;
                    $playerWithdrawRecord->status = PlayerWithdrawRecord::STATUS_SUCCESS;
                    $playerWithdrawRecord->finish_time = date('Y-m-d H:i:s');
                    $playerWithdrawRecord->save();
                    $beforeGameAmount = $player->wallet->money;
                    // 玩家钱包扣减
                    $player->wallet->money = bcsub($player->wallet->money, $playerWithdrawRecord->coins, 2);
                    // 更新玩家统计
                    $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 = 'artificial_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 message_error(admin_trans('player.artificial_withdrawal_error'));
                }
                return message_success(admin_trans('player.artificial_withdrawal_success'));
            });
        });
    }

    /**
     * 人工充值
     * @auth true
     * @group channel
     * @param $data
     * @return Form
     */
    public function artificialRecharge($data): Form
    {
        return Form::create(new $this->model, function (Form $form) use ($data) {
            $form->number('coins', admin_trans('player_recharge_record.fields.coins'))
                ->min(0)
                ->max(100000000)
                ->precision(2)
                ->style(['width' => '100%'])
                ->addonBefore(admin_trans('player.wallet.wallet') . ' ' . $data['money'] ?? 0)
                ->required();
            $form->number('money', admin_trans('player_recharge_record.fields.money'))
                ->min(0)
                ->max(100000000)
                ->precision(2)
                ->style(['width' => '100%']);
            $form->text('currency', admin_trans('player_recharge_record.fields.currency'))->maxlength(10);
            $form->textarea('remark', admin_trans('player_recharge_record.fields.remark'))->maxlength(255)->bindAttr('rows', 4);
            $form->layout('vertical');
            $form->hidden('id')->value($data['id']);
            $form->saving(function (Form $form) {
                /** @var Player $player */
                $player = Player::where('id', $form->input('id'))->whereNull('deleted_at')->first();
                if (empty($player)) {
                    return message_error(admin_trans('player.not_fount'));
                }
                if ($player->status == 0) {
                    return message_error(admin_trans('player.disable'));
                }
                DB::beginTransaction();
                try {
                    $beforeGameAmount = $player->wallet->money;
                    // 生成订单
                    $playerRechargeRecord = new  PlayerRechargeRecord();
                    $playerRechargeRecord->player_id = $player->id;
                    $playerRechargeRecord->department_id = $player->department_id;
                    $playerRechargeRecord->tradeno = createOrderNo();
                    $playerRechargeRecord->player_name = $player->name ?? '';
                    $playerRechargeRecord->money = $form->input('money') ?? 0;
                    $playerRechargeRecord->inmoney = $form->input('money') ?? 0;
                    $playerRechargeRecord->currency = $form->input('currency') ?? '';
                    $playerRechargeRecord->type = PlayerRechargeRecord::TYPE_ARTIFICIAL;
                    $playerRechargeRecord->coins = $form->input('coins');
                    $playerRechargeRecord->status = PlayerRechargeRecord::STATUS_RECHARGED_SUCCESS;
                    $playerRechargeRecord->remark = $form->input('remark');
                    $playerRechargeRecord->finish_time = date('Y-m-d H:i:s');
                    $playerRechargeRecord->user_id = Admin::id() ?? 0;
                    $playerRechargeRecord->user_name = !empty(Admin::user()) ? Admin::user()->toArray()['username'] : '';
                    $playerRechargeRecord->save();
                    $player->wallet->money = bcadd($player->wallet->money, $playerRechargeRecord->coins, 2);
                    $player->player_extend->recharge_amount = bcadd($player->player_extend->recharge_amount, $playerRechargeRecord->coins, 2);
                    $player->push();

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

                    DB::commit();
                } catch (\Exception $e) {
                    DB::rollBack();
                    return message_error(admin_trans('player.artificial_recharge_error'));
                }
                return message_success(admin_trans('player.artificial_recharge_success'));
            });
        });
    }

    /**
     * 玩家钱包
     * @auth true
     * @group channel
     * @param $data
     * @return Form
     */
    public function playerWallet($data): Form
    {
        return Form::create(new $this->model, function (Form $form) use ($data) {
            $form->hidden('id')->default($data['id']);
            $form->row(function (Form $form) {
                $type = $form->getBindField('type');
                $form->radio('type', admin_trans('player.wallet.type'))
                    ->button()
                    ->disabled($form->isEdit())
                    ->default(PlayerMoneyEditLog::TYPE_INCREASE)
                    ->options([
                        admin_trans('player.wallet.deduct'),
                        admin_trans('player.wallet.increase'),
                    ])->required()->span(7);
                $form->hidden('type')->bindAttr('value', $type)
                    ->when(PlayerMoneyEditLog::TYPE_DEDUCT, function (Form $form) {
                        $form->select('deduct_action', admin_trans('player.wallet.action'))
                            ->remoteOptions(admin_url([$this, 'getTranOptions'], ['type' => PlayerMoneyEditLog::TYPE_DEDUCT]))
                            ->required()->span(16)->style(['margin-left' => '22px']);
                    })->when(PlayerMoneyEditLog::TYPE_INCREASE, function (Form $form) {
                        $form->select('increase_action', admin_trans('player.wallet.action'))
                            ->remoteOptions(admin_url([$this, 'getTranOptions'], ['type' => PlayerMoneyEditLog::TYPE_INCREASE]))
                            ->required()->span(16)->style(['margin-left' => '22px']);
                    });
            });
            $form->number('money', admin_trans('player.wallet.money'))->min(0)->max(100000000)->precision(2)->style(['width' => '100%'])->addonBefore(admin_trans('player.wallet.wallet') . ' ' . $data['money'] ?? 0)->required();
            $form->textarea('remark', admin_trans('player.wallet.textarea'))->maxlength(255)->bindAttr('rows', 4)->required();
            $form->actions()->hideResetButton();
            $form->saving(function (Form $form) use ($data) {
                /** @var Channel $channel */
                $channel = Channel::where('department_id', Admin::user()->department_id)->first();
                if ($channel->wallet_action_status == 0) {
                    return message_error(admin_trans('player.wallet_action_status_has_closed'));
                }
                return $this->store([
                    'id' => $form->input('id'),
                    'type' => $form->input('type'),
                    'deduct_action' => $form->input('deduct_action'),
                    'increase_action' => $form->input('increase_action'),
                    'money' => $form->input('money'),
                    'remark' => $form->input('remark'),
                ]);
            });
            $form->layout('vertical');
        });
    }

    /**
     * 钱包操作
     * @param $data
     * @return Msg
     */
    public function store($data): Msg
    {
        try {
            DB::beginTransaction();
            playerManualSystem($data);
            DB::commit();
        } catch (\Exception $e) {
            DB::rollBack();
            return message_error(admin_trans('player.wallet.wallet_operation_failed'));
        }
        return message_success(admin_trans('player.wallet.wallet_operation_success'));
    }

    /**
     * 钱包操作类型
     * @param $type
     * @return mixed
     */
    public function getTranOptions($type)
    {
        $options = [];
        if ($type == PlayerMoneyEditLog::TYPE_INCREASE) {
            $transactionType = [
                PlayerMoneyEditLog::ACTIVITY_GIVE,
                PlayerMoneyEditLog::ADMIN_INCREASE,
                PlayerMoneyEditLog::OTHER
            ];
        } else {
            $transactionType = [
                PlayerMoneyEditLog::ADMIN_DEDUCT,
                PlayerMoneyEditLog::OTHER
            ];
        }

        foreach ($transactionType as $item) {
            $options[] = [
                'value' => $item,
                'label' => admin_trans('player.wallet.wallet_type.' . $item),
            ];
        }

        return Response::success($options);
    }

    /**
     * 处理标签
     * @param array $value
     * @return Html
     */
    public function handleTagIds(array $value): Html
    {
        $options = $this->getPlayerTagOptions($value);
        $html = Html::create();
        foreach ($options as $option) {
            $html->content(
                Tag::create($option)
                    ->color('success')
            );
        }
        return $html;
    }

    /**
     * 获取玩家标签选项(筛选id)
     * @param array $ids
     * @return array
     */
    public function getPlayerTagOptions(array $ids = []): array
    {
        $idsStr = json_encode($ids);
        $cacheKey = md5("player_tag_options_ids_$idsStr");
        if (Cache::has($cacheKey)) {
            return Cache::get($cacheKey);
        } else {
            if (!empty($ids)) {
                $data = (new PlayerTag())->whereIn('id', $ids)->select(['name', 'id'])->get()->toArray();
                $data = $data ? array_column($data, 'name', 'id') : [];
                Cache::set($cacheKey, $data, 24 * 60 * 60);

                return $data;
            }
            return [];
        }
    }

    /**
     * 获取玩家标签(筛选id)
     * @return array
     */
    public function getPlayerTagOptionsFilter(): array
    {
        $cacheKey = "doc_player_tag_options_filter";
        if (Cache::has($cacheKey)) {
            return Cache::get($cacheKey);
        } else {
            $data = (new PlayerTag())->select(['name', 'id'])->get()->toArray();
            $data = $data ? array_column($data, 'name', 'id') : [];
            Cache::set($cacheKey, $data, 24 * 60 * 60);

            return $data;
        }
    }

    /**
     * 渠道玩家
     * @auth true
     * @group channel
     * @return Form
     */
    public function form(): Form
    {
        $options = [];
        foreach (config('def_avatar') as $key => $item) {
            $options[$key] = Avatar::create()->style(['padding' => '1px'])->src($item)->shape('square');
        }
        return Form::create(new $this->model(), function (Form $form) use ($options) {
            if ($form->isEdit()) {
                $form->title(admin_trans('player.details'));
                $form->row(function (Form $form) use ($options) {
                    $form->column(function (Form $form) use ($options) {
                        $form->text('phone', admin_trans('player.fields.phone'))->maxlength(50)->ruleNumber()
                            ->rule([
                                (string)Rule::unique(plugin()->webman->config('database.player_model'))->ignore($form->input('id')) => admin_trans('player.phone_exist'),
                            ])
                            ->disabled(true);
                        $form->text('name', admin_trans('player.fields.name'))->maxlength(50);
                        $form->radio('avatar_type', admin_trans('player.avatar_type'))
                            ->button()
                            ->default(is_numeric($form->driver()->get('avatar')) ? 2 : 1)
                            ->options([
                                1 => admin_trans('player.upload_avatar'),
                                2 => admin_trans('player.def_avatar')
                            ])
                            ->when(1, function (Form $form) {
                                $form->file('avatar', admin_trans('player.fields.avatar'))
                                    ->value(is_numeric($form->driver()->get('avatar')) ? '' : $form->driver()->get('avatar'))
                                    ->ext('jpg,png,jpeg')
                                    ->type('image')
                                    ->fileSize('1m')
                                    ->hideFinder()
                                    ->paste();
                            })->when(2, function (Form $form) use ($options) {
                                $form->radio('def_avatar', admin_trans('player.def_avatar'))
                                    ->default(1)
                                    ->options($options);
                            });
                        $form->text('player_extend.id_number', admin_trans('player_extend.fields.id_number'))->ruleAlphaNum()->maxlength(20);
                        $form->desc('the_last_player_login_record.created_at', admin_trans('player.fields.login_at'))->value($form->input('the_last_player_login_record.created_at') ? date('Y-m-d H:i:s', strtotime($form->input('the_last_player_login_record.created_at'))) : '');
                        $form->desc('created_at', admin_trans('player.fields.created_at'))->value($form->input('created_at') ? date('Y-m-d H:i:s', strtotime($form->input('created_at'))) : '');
                        $form->desc('player_register_record.ip', admin_trans('player.fields.register_ip'));
                        $form->desc('player_register_record.register_domain', admin_trans('player.fields.register_domain'));
                    })->span(12);

                    $form->column(function (Form $form) {
                        $form->text('player_extend.address', admin_trans('player_extend.fields.address'))->maxlength(255);
                        $form->date('player_extend.birthday', admin_trans('player_extend.fields.birthday'));
                        $form->text('player_extend.email', admin_trans('player_extend.fields.email'))->ruleEmail()->maxlength(20);
                        $form->text('player_extend.line', admin_trans('player_extend.fields.line'))->ruleAlphaNum()->maxlength(20);
                        $form->textarea('player_extend.remark', admin_trans('player_extend.fields.remark'))
                            ->showCount()
                            ->rule(['max:255' => admin_trans('player_extend.fields.remark')]);
                        $playerBank = PlayerBank::query()->where('player_id', $form->driver()->get('id'))->get()->toArray();
                        foreach ($playerBank as $key => $item) {
                            $form->row(function (Form $form) use ($item, $key) {
                                $form->text('bank_name'.$key, admin_trans('player.bank_name'))
                                    ->value($item['bank_name'] ?? 0)
                                    ->disabled(true);
                                $form->text('account_name'.$key, admin_trans('player.account_name'))
                                    ->value($item['account_name'] ?? 0)
                                    ->disabled(true);
                                $form->text('account'.$key, admin_trans('player.account'))
                                    ->value($item['account'] ?? 0)
                                    ->disabled(true);
                            });
                        }
                    })->span(12);
                });
            } else {
                $form->title(admin_trans('player.add_player'));
                $form->text('phone', admin_trans('player.fields.phone'))->maxlength(50)->ruleAlphaNum()->required();
                $form->radio('avatar_type', admin_trans('player.avatar_type'))
                    ->button()
                    ->default(2)
                    ->options([
                        1 => admin_trans('player.upload_avatar'),
                        2 => admin_trans('player.def_avatar')
                    ])
                    ->when(1, function (Form $form) {
                        $form->image('avatar', admin_trans('player.fields.avatar'))->ext('jpg,png,jpeg')->fileSize('1m');
                    })->when(2, function (Form $form) use ($options) {
                        $form->radio('def_avatar', admin_trans('player.def_avatar'))
                            ->default(1)
                            ->options($options);
                    });
                $form->select('country_code', admin_trans('player.fields.country_code'))->options([
                    PhoneSmsLog::COUNTRY_CODE_MY => PhoneSmsLog::COUNTRY_CODE_MY,
                ])->required();
                $form->text('name', admin_trans('player.fields.name'))->maxlength(50)->required();
                $form->password('password', admin_trans('player.new_password'))
                    ->rule([
                        'confirmed' => admin_trans('player.password_confim_validate'),
                        'min:6' => admin_trans('player.password_min_number')
                    ])
                    ->value('')
                    ->required();
                $form->password('password_confirmation', admin_trans('player.confim_password'))
                    ->required();
            }
            $form->saved(function () {
                return message_success(admin_trans('player.save_player_info_success'));
            });
            $form->saving(function (Form $form) {
                if ($form->isEdit()) {
                    $orgData = $form->driver()->get();
                    /** @var Player $player */
                    $player = Player::find($orgData['id']);
                    if (empty($player)) {
                        return message_error(admin_trans('player.not_fount'));
                    }
                    DB::beginTransaction();
                    try {
                        $player->name = $form->input('name');
                        $player->avatar = $form->input('avatar_type') == 1 ? $form->input('avatar') : $form->input('def_avatar');
                        $player->save();
                        PlayerExtend::query()->updateOrCreate(['player_id' => $orgData['id']], [
                            'address' => $form->input('player_extend.address'),
                            'birthday' => $form->input('player_extend.birthday'),
                            'id_number' => $form->input('player_extend.id_number'),
                            'email' => $form->input('player_extend.email'),
                            'line' => $form->input('player_extend.line'),
                            'remark' => $form->input('player_extend.remark'),
                            'player_id' => $orgData['id']]);
                        DB::commit();
                    } catch (\Exception $e) {
                        DB::rollBack();
                        return message_error($e->getMessage());
                    }
                    return message_success(admin_trans('player.save_player_info_success'));
                } else {
                    $phone = $form->input('phone');
                    $password = $form->input('password');
                    $country_code = $form->input('country_code');
                    /** @var $player Player */
                    $player = Player::query()->where('phone', $country_code.$phone)->first();
                    if (!empty($player)) {
                        return message_error(admin_trans('player.phone_has_register'));
                    }
                    /** @var Channel $channel */
                    $channel = Channel::where('department_id', Admin::user()->department_id)->first();
                    if (empty($channel)) {
                        return message_error(admin_trans('channel.not_fount'));
                    }
                    DB::beginTransaction();
                    try {
                        $player = new Player();
                        $player->phone = $country_code.$phone;
                        $player->name = $form->input('name');
                        if ($form->input('avatar_type') == 1) {
                            $player->avatar = $form->input('avatar') ?? config('def_avatar.1');
                        }
                        if ($form->input('avatar_type') == 2) {
                            $player->avatar = $form->input('def_avatar') ?? config('def_avatar.1');
                        }
                        $player->country_code = $country_code;
                        $player->type = Player::TYPE_PLAYER;
                        $player->currency = $channel->currency;
                        $player->password = $password;
                        $player->uuid = gen_uuid();
                        $player->department_id = Admin::user()->department_id;
                        $player->recommend_code = createCode();
                        $player->save();
                        
                        addPlayerExtend($player, [
                            'email' => $data['email'] ?? ''
                        ]);
                        addRegisterRecord($player->id, PlayerRegisterRecord::TYPE_ADMIN, $player->department_id);

                        DB::commit();
                    } catch (\Exception $e) {
                        DB::rollBack();
                        return message_error($e->getMessage());
                    }
                    return message_success(admin_trans('player.save_player_info_success'));
                }
            });
        });
    }

    /**
     * 玩家记录
     * @param $id
     * @auth true
     * @group channel
     * @return Card
     */
    public function playerRecord($id): Card
    {
        $tabs = Tabs::create()
            ->pane(admin_trans('player.player_recharge_record'), $this->rechargeRecord($id))
            ->pane(admin_trans('player.player_withdraw_record'), $this->withdrawalRecords($id))
            ->pane(admin_trans('player.player_delivery_record'), $this->playerDeliveryRecord($id))
            ->type('card');
        return Card::create($tabs);
    }

    /**
     * 钱包操作
     * @param $id
     * @return Grid
     */
    public function playerDeliveryRecord($id): Grid
    {
        return Grid::create(new $this->playerDeliveryRecord, function (Grid $grid) use ($id) {
            $lang = Container::getInstance()->translator->getLocale();
            $grid->title(admin_trans('promoter_profit_record.player_activity_phase_record_title'));
            $grid->model()
                ->where('player_id', $id)
                ->whereIn('type', [
                    PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_ADD,
                    PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_DEDUCT,
                ])
                ->orderBy('id', 'desc');
            $exAdminFilter = Request::input('ex_admin_filter', []);
            if (!empty($exAdminFilter)) {
                if (isset($exAdminFilter['created_at_start']) && !empty($exAdminFilter['created_at_start'])) {
                    $grid->model()->where('created_at', '>=', $exAdminFilter['created_at_start']);
                }
                if (isset($exAdminFilter['created_at_end']) && !empty($exAdminFilter['created_at_end'])) {
                    $grid->model()->where('created_at', '<=', $exAdminFilter['created_at_end']);
                }
            }
            $grid->autoHeight();
            $grid->bordered(true);
            $grid->column('id', admin_trans('player_delivery_record.fields.id'))->align('center');
            $grid->column('source', admin_trans('player_delivery_record.fields.source'))->display(function ($val, PlayerDeliveryRecord $data) use ($lang) {
                switch ($data->type) {
                    case PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_ADD:
                    case PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_DEDUCT:
                        return Tag::create(trans($val, [], 'message', $lang))->color('red');
                    default:
                        return '';
                }
            })->align('center');
            $grid->column('type', admin_trans('player_delivery_record.fields.type'))
                ->display(function ($value) {
                    switch ($value) {
                        case PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_ADD:
                            $tag = Tag::create(admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_ADD))->color('#2db7f5');
                            break;
                        case PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_DEDUCT:
                            $tag = Tag::create(admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_DEDUCT))->color('#108ee9');
                            break;
                        default:
                            $tag = '';
                    }
                    return Html::create()->content([
                        $tag
                    ]);
                })->align('center')->sortable();
            $grid->column('amount', admin_trans('player_delivery_record.fields.amount'))->display(function ($val, PlayerDeliveryRecord $data) {
                if ($data->amount == 0) {
                    return Html::create()->content([$val])->style(['color' => 'green']);
                }
                switch ($data->type) {
                    case PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_DEDUCT:
                        return Html::create()->content(['-' . $val])->style(['color' => '#cd201f']);
                    default:
                        return Html::create()->content(['+' . $val])->style(['color' => 'green']);
                }
            })->align('center');
            $grid->column('user_name', admin_trans('player_delivery_record.fields.user_name'))->display(function ($val, PlayerDeliveryRecord $data) {
                $name = '--';
                if (in_array($data->type, [PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_ADD, PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_DEDUCT])) {
                    $name = $data->user_name ?? '管理员';
                }
                return Html::create()->content([
                    Html::div()->content($name),
                ]);
            });
            $grid->column('created_at', admin_trans('player_delivery_record.fields.created_at'))->align('center')->ellipsis(true);
            $grid->hideDelete();
            $grid->hideSelection();
            $grid->hideTrashed();
            $grid->actions(function (Actions $actions) {
                $actions->hideDel();
            });
            $grid->filter(function (Filter $filter) {
                $filter->eq()->select('type')
                    ->placeholder(admin_trans('player_delivery_record.fields.type'))
                    ->showSearch()
                    ->style(['width' => '200px'])
                    ->dropdownMatchSelectWidth()
                    ->options([
                        PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_ADD => admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_ADD),
                        PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_DEDUCT => admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_DEDUCT),
                    ]);
                $filter->form()->hidden('created_at_start');
                $filter->form()->hidden('created_at_end');
                $filter->form()->dateTimeRange('created_at_start', 'created_at_end', '')->placeholder([admin_trans('public_msg.created_at_start'), admin_trans('public_msg.created_at_end')]);
            });
        });
    }

    /**
     * 提现记录
     * @param $id
     * @return Grid
     */
    public function withdrawalRecords($id): Grid
    {
        return Grid::create(new $this->withdraw(), function (Grid $grid) use ($id) {
            $grid->title(admin_trans('player_withdraw_record.title'));
            $grid->model()->with(['player'])->where('player_id', $id)->where('status', PlayerWithdrawRecord::STATUS_SUCCESS)->orderBy('created_at', 'desc');
            $exAdminFilter = Request::input('ex_admin_filter', []);
            if (!empty($exAdminFilter)) {
                if (isset($exAdminFilter['created_at_start']) && !empty($exAdminFilter['created_at_start'])) {
                    $grid->model()->where('created_at', '>=', $exAdminFilter['created_at_start']);
                }
                if (isset($exAdminFilter['created_at_end']) && !empty($exAdminFilter['created_at_end'])) {
                    $grid->model()->where('created_at', '<=', $exAdminFilter['created_at_end']);
                }
                if (isset($exAdminFilter['finish_time_start']) && !empty($exAdminFilter['finish_time_start'])) {
                    $grid->model()->where('finish_time', '>=', $exAdminFilter['finish_time_start']);
                }
                if (isset($exAdminFilter['finish_time_end']) && !empty($exAdminFilter['finish_time_end'])) {
                    $grid->model()->where('finish_time', '<=', $exAdminFilter['finish_time_end']);
                }
            }
            $grid->bordered();
            $grid->autoHeight();
            $grid->column('id', admin_trans('player_withdraw_record.fields.id'))->ellipsis(true)->align('center')->fixed(true);
            $grid->column('player_phone', admin_trans('player_withdraw_record.fields.player_phone'))->display(function ($val, PlayerWithdrawRecord $data) {
                $image = (isset($data->player->avatar) && !empty($data->player->avatar)) ? Avatar::create()->src($data->player->avatar) : Avatar::create()->icon(Icon::create('UserOutlined'));
                return Html::create()->content([
                    $image,
                    Html::div()->content($val)
                ]);
            })->align('center')->ellipsis(true)->fixed(true);
            $grid->column('tradeno', admin_trans('player_withdraw_record.fields.tradeno'))->ellipsis(true)->copy()->align('center');
            $grid->column('money', admin_trans('player_withdraw_record.fields.money'))->display(function ($val, PlayerWithdrawRecord $data) {
                return $val . ' ' . ($data->currency == 'TALK' ? 'Q币' : $data->currency);
            })->ellipsis(true)->align('center');
            $grid->column('coins', admin_trans('player_withdraw_record.fields.coins'))->align('center');
            $grid->column(function (Grid $grid) {
                $grid->column('bank_name', admin_trans('player_withdraw_record.fields.bank_name'))->copy()->align('center');
                $grid->column('account_name', admin_trans('player_withdraw_record.fields.account_name'))->copy()->align('center');
                $grid->column('account', admin_trans('player_withdraw_record.fields.account'))->copy()->align('center');
            }, admin_trans('player_withdraw_record.player_bank'))->ellipsis(true);
            $grid->column('type', admin_trans('player_withdraw_record.fields.type'))->display(function ($val) {
                switch ($val) {
                    case PlayerRechargeRecord::TYPE_ACTIVITY:
                        return Tag::create(admin_trans('player_recharge_record.type.' . $val))
                            ->color('#55acee');
                    case PlayerRechargeRecord::TYPE_REGULAR:
                        return Tag::create(admin_trans('player_recharge_record.type.' . $val))
                            ->color('#3b5999');
                    case PlayerRechargeRecord::TYPE_ARTIFICIAL:
                        return Tag::create(admin_trans('player_recharge_record.type.' . $val))
                            ->color('#cd201f');
                    default:
                        return '';
                }
            })->ellipsis(true)->align('center');
            $grid->column('status', admin_trans('player_withdraw_record.fields.status'))
                ->display(function () {
                    return Tag::create(admin_trans('player_withdraw_record.status.' . PlayerWithdrawRecord::STATUS_SUCCESS))->color('#87d068');
                })->align('center')->ellipsis(true)->sortable();
            $grid->column('created_at', admin_trans('player_withdraw_record.fields.created_at'))->ellipsis(true)->sortable()->align('center');
            $grid->column('finish_time', admin_trans('player_withdraw_record.fields.finish_time'))->ellipsis(true)->fixed('right')->sortable()->align('center');
            $grid->hideDelete();
            $grid->hideSelection();
            $grid->actions(function (Actions $actions) {
                $actions->hideDel();
                $actions->hideEdit();
            });
            $grid->filter(function (Filter $filter) {
                $filter->like()->text('tradeno')->placeholder(admin_trans('player_withdraw_record.fields.tradeno'));
                $filter->form()->hidden('created_at_start');
                $filter->form()->hidden('created_at_end');
                $filter->form()->dateTimeRange('created_at_start', 'created_at_end', '')->placeholder([admin_trans('public_msg.created_at_start'), admin_trans('public_msg.created_at_end')]);
                $filter->form()->hidden('finish_time_start');
                $filter->form()->hidden('finish_time_end');
                $filter->form()->dateTimeRange('finish_time_start', 'finish_time_end', '')->placeholder([admin_trans('player_withdraw_record.fields.finish_time'), admin_trans('player_withdraw_record.fields.finish_time')]);
            });
        });
    }

    /**
     * 充值记录
     * @param $id
     * @return Grid
     */
    public function rechargeRecord($id): Grid
    {
        return Grid::create(new $this->recharge(), function (Grid $grid) use ($id) {
            $grid->title(admin_trans('player_recharge_record.title'));
            $grid->bordered();
            $grid->autoHeight();
            $grid->model()->with(['player'])->where('player_id', $id)->where('status', PlayerRechargeRecord::STATUS_RECHARGED_SUCCESS)->orderBy('created_at', 'desc');
            $exAdminFilter = Request::input('ex_admin_filter', []);
            if (!empty($exAdminFilter)) {
                if (isset($exAdminFilter['created_at_start']) && !empty($exAdminFilter['created_at_start'])) {
                    $grid->model()->where('created_at', '>=', $exAdminFilter['created_at_start']);
                }
                if (isset($exAdminFilter['created_at_end']) && !empty($exAdminFilter['created_at_end'])) {
                    $grid->model()->where('created_at', '<=', $exAdminFilter['created_at_end']);
                }
                if (isset($exAdminFilter['finish_time_start']) && !empty($exAdminFilter['finish_time_start'])) {
                    $grid->model()->where('finish_time', '>=', $exAdminFilter['finish_time_start']);
                }
                if (isset($exAdminFilter['finish_time_end']) && !empty($exAdminFilter['finish_time_end'])) {
                    $grid->model()->where('finish_time', '<=', $exAdminFilter['finish_time_end']);
                }
            }
            $grid->column('id', admin_trans('player_recharge_record.fields.id'))->ellipsis(true)->fixed(true)->align('center');
            $grid->column('player.name', admin_trans('player_recharge_record.fields.player_name'))->display(function ($val, PlayerRechargeRecord $data) {
                $image = (isset($data->player->avatar) && !empty($data->player->avatar)) ? Avatar::create()->src($data->player->avatar) : Avatar::create()->icon(Icon::create('UserOutlined'));
                return Html::create()->content([
                    $image,
                    Html::div()->content($val)
                ]);
            })->ellipsis(true)->fixed(true)->align('center');
            $grid->column('tradeno', admin_trans('player_recharge_record.fields.tradeno'))->ellipsis(true)->copy();
            $grid->column('channel.name', admin_trans('player_recharge_record.fields.department_id'))->ellipsis(true)->align('center');
            $grid->column('type', admin_trans('player_recharge_record.fields.type'))->display(function ($val) {
                switch ($val) {
                    case PlayerRechargeRecord::TYPE_REGULAR:
                        return Tag::create(admin_trans('player_recharge_record.type.' . $val))
                            ->color('#55acee');
                    case PlayerRechargeRecord::TYPE_ACTIVITY:
                        return Tag::create(admin_trans('player_recharge_record.type.' . $val))
                            ->color('#3b5999');
                    case PlayerRechargeRecord::TYPE_ARTIFICIAL:
                        return Tag::create(admin_trans('player_recharge_record.type.' . $val))
                            ->color('#cd201f');
                    default:
                        return '';
                }
            })->ellipsis(true)->align('center');
            $grid->column('money', admin_trans('player_recharge_record.fields.money'))->display(function ($val, PlayerRechargeRecord $data) {
                return $val . ' ' . ($data->currency == 'TALK' ? 'Q币' : $data->currency);
            })->ellipsis(true)->align('center');
            $grid->column('coins', admin_trans('player_recharge_record.fields.coins'))->ellipsis(true)->align('center');
            $grid->column(function (Grid $grid) {
                $grid->column('bank_name', admin_trans('channel_recharge_method.fields.bank_name'))->copy()->align('center');
                $grid->column('sub_bank', admin_trans('channel_recharge_method.fields.sub_bank'))->copy()->align('center');
                $grid->column('owner', admin_trans('channel_recharge_method.fields.owner'))->copy()->align('center');
                $grid->column('account', admin_trans('channel_recharge_method.fields.account'))->copy()->align('center');
            }, admin_trans('channel_recharge_setting.recharge_setting_info'))->ellipsis(true);
            $grid->column('status', admin_trans('player_recharge_record.fields.status'))->display(function () {
                return Tag::create(admin_trans('player_recharge_record.status_success'))->color('#87d068');
            })->ellipsis(true)->align('center');
            $grid->column('created_at', admin_trans('player_recharge_record.fields.created_at'))->ellipsis(true)->sortable()->align('center');
            $grid->column('finish_time', admin_trans('player_recharge_record.fields.finish_time'))->ellipsis(true)->fixed('right')->sortable()->align('center');
            $grid->hideDelete();
            $grid->hideSelection();
            $grid->actions(function (Actions $actions) {
                $actions->hideDel();
                $actions->hideEdit();
            });
            $grid->filter(function (Filter $filter) {
                $filter->eq()->select('type')
                    ->showSearch()
                    ->style(['width' => '200px'])
                    ->dropdownMatchSelectWidth()
                    ->placeholder(admin_trans('player_recharge_record.fields.type'))
                    ->options([
                        PlayerRechargeRecord::TYPE_REGULAR => admin_trans('player_recharge_record.type.' . PlayerRechargeRecord::TYPE_REGULAR),
                        PlayerRechargeRecord::TYPE_ACTIVITY => admin_trans('player_recharge_record.type.' . PlayerRechargeRecord::TYPE_ACTIVITY),
                        PlayerRechargeRecord::TYPE_ARTIFICIAL => admin_trans('player_recharge_record.type.' . PlayerRechargeRecord::TYPE_ARTIFICIAL),
                    ]);
                $filter->like()->text('tradeno')->placeholder(admin_trans('player_recharge_record.fields.tradeno'));
                $filter->form()->hidden('created_at_start');
                $filter->form()->hidden('created_at_end');
                $filter->form()->dateTimeRange('created_at_start', 'created_at_end', '')->placeholder([admin_trans('public_msg.created_at_start'), admin_trans('public_msg.created_at_end')]);
                $filter->form()->hidden('finish_time_start');
                $filter->form()->hidden('finish_time_end');
                $filter->form()->dateTimeRange('finish_time_start', 'finish_time_end', '')->placeholder([admin_trans('player_recharge_record.fields.finish_time'), admin_trans('player_recharge_record.fields.finish_time')]);

            });
        });
    }

    /**
     * 打码量记录
     * @param $id
     * @return Grid
     */
    public function playerChipRecord($id): Grid
    {
        return Grid::create(new $this->playerChipRecord(), function (Grid $grid) use ($id) {
            $grid->title(admin_trans('player_chip_record.title'));
            $grid->bordered();
            $grid->autoHeight();
            $grid->model()->with(['channel', 'player'])
                ->where('player_id', $id)
                ->orderBy('created_at', 'desc');
            $exAdminFilter = Request::input('ex_admin_filter', []);
            $query = clone $grid->model();
            $totalData = $query->where(function ($query) use($exAdminFilter) {
                if(!empty($exAdminFilter['created_at'])) {
                    $query->whereBetween('created_at', $exAdminFilter['created_at']);
                }
            })->sum('chip_amount');
            $layout = Layout::create();
            $layout->row(function (Row $row) use ($totalData) {
                $row->gutter([10, 0]);
                $row->column(
                    Card::create([
                        Row::create()->column(Statistic::create()->value($totalData)
                            ->prefix(admin_trans('player_chip_record.fields.chip_amount'))
                            ->valueStyle([
                                'font-size' => '14px',
                                'font-weight' => '500',
                                'text-align' => 'center'
                            ])),
                    ])->bodyStyle([
                        'display' => 'flex',
                        'align-items' => 'center',
                        'height' => '30px',
                        'padding' => '0px'
                    ])->hoverable()->headStyle(['height' => '0px', 'border-bottom' => '0px', 'min-height' => '0px'])
                    , 4);
            })->style(['background' => '#fff']);
            $grid->tools([
                $layout
            ]);
            $grid->column('id', admin_trans('player_chip_record.fields.id'))->align('center');
            $grid->column('channel.name', admin_trans('channel.fields.name'))->align('center');
            $grid->column('chip_amount', admin_trans('player_chip_record.fields.chip_amount'))->display(function ($val, PlayerChipRecord $data) {
                if ($val == 0) {
                    return Html::create()->content(['+' . $val])->style(['color' => 'green']);
                }
                switch ($data->type) {
                    case PlayerChipRecord::TYPE_DEC:
                        return Html::create()->content(['-' . $val])->style(['color' => '#cd201f']);
                    default:
                        return Html::create()->content(['+' . $val])->style(['color' => 'green']);
                }
            })->align('center');
            $grid->column('must_chip_amount', admin_trans('player_chip_record.fields.must_chip_amount'))->display(function ($val, PlayerChipRecord $data) {
                if ($val == 0) {
                    return Html::create()->content(['+' . $val])->style(['color' => 'green']);
                }
                switch ($data->type) {
                    case PlayerChipRecord::TYPE_DEC:
                        return Html::create()->content(['-' . $val])->style(['color' => '#cd201f']);
                    default:
                        return Html::create()->content(['+' . $val])->style(['color' => 'green']);
                }
            })->align('center');
            $grid->column('record_type', admin_trans('player_chip_record.fields.record_type'))->display(function ($val) {
                switch ($val) {
                    case PlayerChipRecord::RECORD_TYPE_SIGN:
                    case PlayerChipRecord::RECORD_TYPE_RECHARGE:
                    case PlayerChipRecord::RECORD_TYPE_FIRST_RECHARGE_REWARD:
                        $tag = Tag::create(admin_trans('player_chip_record.record_type.' . $val))
                            ->color('#55acee');
                        break;
                    case PlayerChipRecord::RECORD_TYPE_ACTIVITY:
                    case PlayerChipRecord::RECORD_TYPE_GAME:
                    case PlayerChipRecord::RECORD_TYPE_BET_REBATE:
                        $tag = Tag::create(admin_trans('player_chip_record.record_type.' . $val))
                            ->color('#3b5999');
                        break;
                    case PlayerChipRecord::RECORD_TYPE_COMMISSION:
                    case PlayerChipRecord::RECORD_TYPE_BANKRUPTCY:
                        $tag = Tag::create(admin_trans('player_chip_record.record_type.' . $val))
                            ->color('#cd201f');
                        break;
                    default:
                        return '';
                }
                return Html::create()->content([
                    $tag,
                ]);
            })->align('center');
            $grid->column('amount', admin_trans('player_chip_record.fields.amount'))->align('center');
            $grid->column('created_at', admin_trans('player_chip_record.fields.created_at'))->sortable()->align('center');
            $grid->hideDelete();
            $grid->hideSelection();
            $grid->actions(function (Actions $actions) {
                $actions->hideDel();
                $actions->hideEdit();
            });
            $grid->filter(function (Filter $filter) {
                $filter->eq()->select('record_type')
                    ->showSearch()
                    ->style(['width' => '200px'])
                    ->dropdownMatchSelectWidth()
                    ->placeholder(admin_trans('player_chip_record.fields.record_type'))
                    ->options([
                        PlayerChipRecord::RECORD_TYPE_SIGN => admin_trans('player_chip_record.record_type.' . PlayerChipRecord::RECORD_TYPE_SIGN),
                        PlayerChipRecord::RECORD_TYPE_RECHARGE => admin_trans('player_chip_record.record_type.' . PlayerChipRecord::RECORD_TYPE_RECHARGE),
                        PlayerChipRecord::RECORD_TYPE_ACTIVITY => admin_trans('player_chip_record.record_type.' . PlayerChipRecord::RECORD_TYPE_ACTIVITY),
                        PlayerChipRecord::RECORD_TYPE_GAME => admin_trans('player_chip_record.record_type.' . PlayerChipRecord::RECORD_TYPE_GAME),
                        PlayerChipRecord::RECORD_TYPE_COMMISSION => admin_trans('player_chip_record.record_type.' . PlayerChipRecord::RECORD_TYPE_COMMISSION),
                        PlayerChipRecord::RECORD_TYPE_BANKRUPTCY => admin_trans('player_chip_record.record_type.' . PlayerChipRecord::RECORD_TYPE_BANKRUPTCY),
                        PlayerChipRecord::RECORD_TYPE_BET_REBATE => admin_trans('player_chip_record.record_type.' . PlayerChipRecord::RECORD_TYPE_BET_REBATE),
                        PlayerChipRecord::RECORD_TYPE_FIRST_RECHARGE_REWARD => admin_trans('player_chip_record.record_type.' . PlayerChipRecord::RECORD_TYPE_FIRST_RECHARGE_REWARD),
                    ]);
                $filter->between()->dateTimeRange('created_at')->placeholder([admin_trans('player_chip_record.fields.created_at'), admin_trans('player_chip_record.fields.created_at')]);

            });
            $grid->quickSearch();
        });
    }

    

    /**
     * 设置推广员
     * @auth true
     * @group channel
     * @param $id
     * @return Form
     */
    public function setPromoter($id): Form
    {
        /** @var PlayerPromoter $promoter */
        $promoter = PlayerPromoter::with(['parent_promoter'])->where('player_id', $id)->first();
        return Form::create($promoter ?? new $this->promoter(), function (Form $form) use ($id) {
            $form->push(Html::markdown('><font size=1 color="#ff4d4f">' . admin_trans('player_promoter.submit_confirm') . '</font>'));
            /** @var PlayerPromoter $model */
            $model = $form->driver()->model();
            $maxRatio = $model->parent_promoter->ratio ?? 100;
            $form->text('name')
                ->value($model->name ?? '')
                ->maxlength(30)
                ->required()->addonBefore(admin_trans('player_promoter.fields.name'));
            $form->text('ratio')
                ->value($model->ratio ?? '')
                ->rulePattern('^[0-9]+(.[0-9]{1,2})?$', admin_trans('validator.twoDecimal'))
                ->rule([
                    'max:' . $maxRatio => admin_trans('validator.max', null, ['{max}' => $maxRatio]),
                    'min:0' => admin_trans('validator.min', null, ['{min}' => 0]),
                    'regex:/^[0-9]+(.[0-9]{1,2})?$/' => admin_trans('validator.twoDecimal'),
                ])
                ->required()
                ->addonAfter('%')
                ->help(!empty($model->parent_promoter->ratio) ? admin_trans('player_promoter.ratio_help_parent', null, ['{max_ratio}' => $maxRatio]) : admin_trans('player_promoter.ratio_help_platform', null, ['{max_ratio}' => $maxRatio]))
                ->placeholder(admin_trans('player_promoter.ratio_placeholder', null, ['{max_ratio}' => $maxRatio]))
                ->addonBefore(admin_trans('player_promoter.fields.ratio'));
            $form->saving(function (Form $form) use ($id) {
                return $this->savePromoter($id, $form->input('ratio'), $form->input('name'));
            });
        });
    }

    /**
     * 保存推广员信息
     * @param $id
     * @param $ratio
     * @param string $name
     * @return Msg
     */
    public function savePromoter($id, $ratio, string $name = ''): Msg
    {
        DB::beginTransaction();
        try {
            /** @var Player $player */
            $player = Player::with(['player_promoter'])->find($id);
            if (empty($player)) {
                throw new Exception(admin_trans('player.not_fount'));
            }
            if (empty($player->player_promoter) && !empty($player->recommend_id)) {
                throw new Exception(admin_trans('player.player_must_not_attributed'));
            }
            $promoter = $player->player_promoter ?? new PlayerPromoter();
            $promoter->ratio = $ratio;
            $promoter->player_id = $id;
            $promoter->recommend_id = $parentPromoter->player_id ?? 0;
            $promoter->department_id = $player->department_id;
            $promoter->name = $name;
            $promoter->path = $player->id;
            $promoter->save();
            // 更新玩家信息
            $player->is_promoter = 1;
            $player->recommend_code = createCode();
            $player->save();
            DB::commit();
        } catch (\Exception $e) {
            DB::rollBack();
            return message_error($e->getMessage());
        }

        return message_success(admin_trans('form.save_success'));
    }

    /**
     * 绑定推广员
     * @auth true
     * @group channel
     * @param $id
     * @return Form|Msg
     */
    public function bindPromoter($id)
    {
        /** @var Player $player */
        $player = Player::query()->find($id);
        if (empty($player)) {
            return message_error(admin_trans('player.player_not_found'));
        }
        if (!empty($player->recommended_code)) {
            return message_error(admin_trans('player.player_has_bind'));
        }
        if ($player->is_promoter > 0) {
            return message_error(admin_trans('player.has_been_promoter'));
        }
        /** @var Channel $channel */
        $channel = Channel::query()->where('department_id', $player->department_id)->first();
        if (empty($channel)) {
            return message_error(admin_trans('player.channel_not_found'));
        }
        if ($channel->promotion_status != 1) {
            return message_error(admin_trans('player.channel_close_promoter'));
        }
        return Form::create($player, function (Form $form) use ($player) {
            $form->push(Html::markdown('><font size=1 color="#ff4d4f">' . admin_trans('player.bind_promoter_confirm') . '</font>'));
            $options = PlayerPromoter::query()
                ->where('department_id', $player->department_id)
                ->where('status', 1)
                ->pluck('name', 'player_id')->toArray();
            $form->select('recommend_id')
                ->style(['width' => '200px'])
                ->options($options);
            $form->saving(function (Form $form) use ($player) {
                /** @var PlayerPromoter $recommendPlayer */
                $recommendPlayer = PlayerPromoter::query()
                    ->where('player_id', $form->input('recommend_id'))
                    ->where('department_id', $player->department_id)->first();
                if (empty($recommendPlayer)) {
                    return message_error(admin_trans('player.promoter_not_found'));
                }
                if ($recommendPlayer->player->status == 0) {
                    return message_error(admin_trans('player.promoter_has_disable'));
                }
                $player->recommend_id = $recommendPlayer->player->id;
                $player->recommended_code = $recommendPlayer->player->recommend_code;
                $player->save();
                $recommendPlayer->increment('player_num');
                return message_success(admin_trans('player.action_success'));
            });
        });
    }


}
