<?php

namespace app\api\controller\v1;

use addons\webman\model\DrawRecord;
use addons\webman\model\Game;
use addons\webman\model\GamePlatform;
use addons\webman\model\Prize;
use app\exception\GameException;
use app\exception\PlayerCheckException;
use app\service\DrawService;
use app\service\game\GameServiceFactory;
use Illuminate\Support\Str;
use Respect\Validation\Exceptions\AllOfException;
use Respect\Validation\Validator as v;
use support\Request;
use support\Response;

class GameController
{
    /** 排除验签 */
    protected $noNeedSign = ['gametest'];

    /**
     * 登录游戏返回游戏地址
     * @param Request $request
     * @return Response
     * @throws PlayerCheckException|GameException
     */
    public function loginGame(Request $request): Response
    {
        $player = checkPlayer();
        $validator = v::key('platform_id', v::notEmpty()->intVal()->setName(trans('platform_id', [], 'message')))
            ->key('game_code', v::stringVal()->setName(trans('game_code', [], 'message')))
            ->key('app_type', v::notEmpty()->intVal()->in([
                GameServiceFactory::DEVICE_TYPE_WEB,
                GameServiceFactory::DEVICE_TYPE_IOS,
                GameServiceFactory::DEVICE_TYPE_ANDROID,
            ])->setName(trans('app_type', [], 'message')));

        $data = $request->all();
        /** @var GamePlatform $gamePlatform */
        $gamePlatform = GamePlatform::query()->find($data['platform_id']);
        if (empty($gamePlatform)) {
            return jsonFailResponse(trans('game_platform_not_found', [], 'message'));
        }
        if ($gamePlatform->status == 0) {
            return jsonFailResponse(trans('game_platform_disabled', [], 'message'));
        }
        /** @var Game $game */
        $game = Game::query()
            ->whereHas('gamePlatform', function ($query) {
                $query->where('status', 1)->whereNull('deleted_at');
            })
            ->where('platform_id', $data['platform_id'])
            ->where('game_code', $data['game_code'])
            ->first();
        if (empty($game)) {
            return jsonFailResponse(trans('game_not_found', [], 'message'));
        }
        if ($game->status == 0) {
            return jsonFailResponse(trans('game_disabled', [], 'message'));
        }
        $lang = locale();
        $lang = Str::replace('_', '-', $lang);
        try {
            $validator->assert($data);
            $res = GameServiceFactory::createService(strtoupper($gamePlatform->name), $player)->login(
                [
                    'CallBackUrl' => '',
                    'lang' => $lang,
                    'gameCode' => $game->game_code,
                    'appType' => $data['app_type'],
                    'platformGameType' => $game->platform_game_type
                ]
            );
            if ($player->wallet->money > 0) {
                GameServiceFactory::createService(strtoupper($gamePlatform->name), $player)->balanceTransferOut();
            }
        } catch (AllOfException $e) {
            return jsonFailResponse(getValidationMessages($e));
        } catch (\Exception $e) {
            return jsonFailResponse($e->getMessage());
        }
        if ($gamePlatform->name == 'MEGA888') {
            $response = [
                'link_game' => $res['url'],
                'jump_url' => 'lobbymegarelease://',
                'jump_url_android' => 'lobbymegarelease://?account='.$res['account'].'&password='.$res['password'],
                'jump_url_ios' => 'lobbymegarelease://account='.$res['account'].'&password='.$res['password'],
                'account' => $res['account'],
                'password' => $res['password'],
            ];
        } elseif ($gamePlatform->name == 'KISS918') {
            $response = [
                'link_game' => $res['url'],
                'jump_url_android' => 'lobbykiss://lobbykiss?account='.$res['account'].'&password='.$res['password'],
                'jump_url_ios' => 'lobbykissgame://account='.$res['account'].'&password='.$res['password'],
                'account' => $res['account'],
                'password' => $res['password'],
            ];
        } else {
            $response = ['link_game' => $res];
        }
        return jsonSuccessResponse('success',$response);
    }

    /**
     * 游戏列表
     * @param Request $request
     * @return Response
     * @throws PlayerCheckException|GameException
     */
    public function gameList(Request $request): Response
    {
        checkPlayer();
        $validator = v::key('game_type', v::notEmpty()->intVal()->setName(trans('game_type', [], 'message')), false)
            ->key('is_hot', v::optional(v::in([0, 1]))->setName(trans('is_hot', [], 'message')), false);

        $data = $request->all();
        try {
            $validator->assert($data);
        } catch (AllOfException $e) {
            return jsonFailResponse(getValidationMessages($e));
        }
        $size = $data['size'] ?? 20;
        $query = Game::query()
            ->with(['gamePlatform' => function ($query) {
                $query->select(['id', 'name', 'status']);
            }])
            ->whereHas('gamePlatform', function ($query) {
                $query->where('status', 1)->whereNull('deleted_at');
            })
            ->where('status', 1)
            ->where('is_online', 1)
            ->when(!empty($data['game_type']), function ($query) use ($data) {
                $query->where('game_type', $data['game_type']);
            })
            ->when(isset($data['is_hot']) && is_numeric($data['is_hot']), function ($query) use ($data) {
                $query->where('is_hot', $data['is_hot']);
            })
            ->when(isset($data['platform_id']) && is_numeric($data['platform_id']), function ($query) use ($data) {
                $query->where('platform_id', $data['platform_id']);
            });
        $list = $query->select(['id', 'platform_id', 'game_code', 'game_type', 'game_image', 'name', 'status', 'player_num_range', 'is_hot', 'is_new', 'sort'])
            ->forPage($data['page'] ?? 1, $size)
            ->orderBy('sort', 'desc')
            ->orderBy('id', 'desc')
            ->get();
        $totalGames = $query->count();
        /** @var Game $game */
        foreach ($list as $game) {
            $game->player_num_range = empty($game->player_num_range) ? 0 : getGamePlayerNum($game->id, $game->player_num_range);
        }

        return jsonSuccessResponse('success', [
            'list' => $list,
            'game_platform' => GamePlatform::query()->where('status', 1)->select(['id', 'title'])->get(),
            'current_page' => $data['page'] ?? 1,
            'total_page' => ceil($totalGames / $size)
        ]);
    }

    /**
     * 奖品列表
     */
    public function getPrizeList(Request $request)
    {
        $player = checkPlayer();
        $prizes = Prize::query()
            ->select('pic', 'name', 'id', 'type')
            ->where('department_id', $player->department_id)
            ->where('status', 1)
            ->orderBy('probability')
            ->get()
            ->toArray();
        $data = [
            'point' => $player->wallet->money,
            'description' => Game::query()->where('id', $player->channel->game_id)->value('description'),
            'prize_list' => $prizes,
        ];
        return jsonSuccessResponse('success',$data);
    }

    /**
     * 抽奖
     */
    public function lottery(Request $request): Response
    {
        $player = checkPlayer();
        if ($player->wallet->money <= 0) {
            return jsonFailResponse('玩家暂无抽奖机会', [], 1000);
        }
        $drawService = new DrawService();
        $result =  $drawService->execute($player, $player->channel->game_id, $player->department_id, $request->getRealIp());
        return jsonSuccessResponse('success',$result);
    }

    /**
     * 抽奖记录
     */
    public function getDrawRecords(Request $request): Response
    {
        $player = checkPlayer();
        $validator = v::key('page', v::intVal()->setName(trans('page', [], 'message')))
            ->key('size', v::intVal()->setName(trans('size', [], 'message')))
            ->key('start_date', v::stringVal()->setName(trans('start_date', [], 'message')))
            ->key('end_date', v::stringVal()->setName(trans('end_date', [], 'message')));
        $data = $request->all();
        try {
            $validator->assert($data);
        } catch (AllOfException $e) {
            return jsonFailResponse(getValidationMessages($e));
        }
        $size = $data['size'] ?? 20;

        $query = DrawRecord::query()
            ->where('department_id', $player->department_id)
            ->where('uid', $player->id)
            ->where('game_id', $player->channel->game_id)
            ->whereBetween('created_at', [$data['start_date'],date('Y-m-d', strtotime("{$data['end_date']} +1 days"))]);
        $record = clone $query;
        $list = $query
            ->select('consume', 'prize_pic', 'prize_name', 'prize_type', 'draw_time', 'ip')
            ->forPage($data['page'] ?? 1, $data['size'] ?? 10)
            ->orderBy('id', 'desc')
            ->get()
            ->toArray();
        $totalRecords = $record->count();
        return jsonSuccessResponse('success', [
            'list' => $list,
            'total_page' => ceil($totalRecords / $size)
        ]);
    }

    public function gametest(Request $request): Response
    {
        return jsonSuccessResponse('', []);
    }
}
