<?php
declare(strict_types=1);

namespace app\api\controller;

use support\Log;
use support\Request;
use support\Response;
use support\think\Db;
use app\api\logic\GameLogic;
use app\api\logic\PlayStartLogic;
use app\api\util\ReturnCode;
use app\dice\helper\AdminScopeHelper;
use app\dice\model\config\DiceConfig;
use app\dice\model\ante_config\DiceAnteConfig;
use app\dice\model\play_record\DicePlayRecord;
use app\dice\model\player\DicePlayer;
use app\dice\model\reward\DiceRewardConfig;
use app\api\controller\BaseController;
use app\api\util\ApiLang;
use plugin\saiadmin\exception\ApiException;

/**
 * 游戏相关接口（购买抽奖券等）
 */
class GameController extends BaseController
{
    /**
     * 获取游戏配置（按 group 分组）
     * GET /api/game/config
     * header: lang = zh | en
     * 返回 data[group] = [ { name, title, value, create_time, update_time }, ... ]
     * - lang=zh 或默认：title/value = 中文
     * - lang=en：若存在英文配置则返回 title_en/value_en，否则回退到中文
     */
    public function config(Request $request): Response
    {
        $configDeptId = $this->resolvePlayerConfigDeptIdFromRequest($request);
        $rows = (new DiceConfig())
            ->field('name,group,title,title_en,value,value_en,create_time,update_time')
            ->where('dept_id', $configDeptId)
            ->select()
            ->toArray();
        $lang = $request->header('lang', 'zh');
        if (!is_string($lang) || $lang === '') {
            $lang = 'zh';
        }
        $langLower = strtolower($lang);
        $isEn = $langLower === 'en' || str_starts_with($langLower, 'en-');
        $data = [];
        foreach ($rows as $row) {
            $group = $row['group'] ?? '';
            if (!isset($data[$group])) {
                $data[$group] = [];
            }
            $title = $row['title'] ?? '';
            $value = $row['value'] ?? '';
            if ($isEn) {
                $titleEn = $row['title_en'] ?? '';
                $valueEn = $row['value_en'] ?? '';
                if ($titleEn !== '') {
                    $title = $titleEn;
                }
                if ($valueEn !== '') {
                    $value = $valueEn;
                }
            }
            $data[$group][] = [
                'name'        => $row['name'] ?? '',
                'title'       => $title,
                'value'       => $value,
                'create_time' => $row['create_time'] ?? '',
                'update_time' => $row['update_time'] ?? '',
            ];
        }
        return $this->success($data);
    }

    /**
     * 购买抽奖券
     * POST /api/game/buyLotteryTickets
     * header: token（由 TokenMiddleware 注入 request->player_id）
     * body: count = 1 | 5 | 10（1次/1coin, 5次/5coin, 10次/10coin）
     */
//    public function buyLotteryTickets(Request $request): Response
//    {
//        $userId = (int) ($request->player_id ?? 0);
//        $count = (int) $request->post('count', 0);
//        if (!in_array($count, [1, 5, 10], true)) {
//            return $this->fail('Invalid lottery ticket purchase', ReturnCode::PARAMS_ERROR);
//        }
//
//        try {
//            $logic = new GameLogic();
//            $data = $logic->buyLotteryTickets($userId, $count);
//            return $this->success($data);
//        } catch (ApiException $e) {
//            $msg = $e->getMessage();
//            if ($msg === '平台币不足') {
//                $player = DicePlayer::find($userId);
//                $coin = $player ? (float) $player->coin : 0;
//                return $this->success(['coin' => $coin], $msg);
//            }
//            return $this->fail($msg, ReturnCode::BUSINESS_ERROR);
//        }
//    }

    /**
     * 获取彩金池（中奖配置表）
     * GET /api/game/lotteryPool
     * header: token
     * 返回 DiceRewardConfig 列表（彩金池/中奖配置），不包含 tier=BIGWIN
     */
    public function lotteryPool(Request $request): Response
    {
        $configDeptId = $this->resolvePlayerConfigDeptIdFromRequest($request);
        $list = DiceRewardConfig::getCachedList($configDeptId);
        $list = array_values(array_filter($list, function ($row) {
            return (string) ($row['tier'] ?? '') !== 'BIGWIN';
        }));

        $lang = $request->header('lang', 'zh');
        if (!is_string($lang) || $lang === '') {
            $lang = 'zh';
        }
        $langLower = strtolower($lang);
        $isEn = $langLower === 'en' || str_starts_with($langLower, 'en-');

        if ($isEn) {
            foreach ($list as $index => $row) {
                $uiEn = '';
                if (is_array($row) && array_key_exists('ui_text_en', $row) && $row['ui_text_en'] !== null) {
                    $uiEn = (string) $row['ui_text_en'];
                }
                if ($uiEn !== '') {
                    $row['ui_text'] = $uiEn;
                }
                //移除掉其中的s_start_index和n_start_index
                $row = array_diff_key($row, ['s_start_index'=>'', 's_end_index'=>'', 'weight'=>'', 'ui_text_en'=>'', 'create_time'=>'', 'update_time'=>'', 'type'=>'']);
                $list[$index] = $row;
            }
        }

        return $this->success($list);
    }

    /**
     * 获取底注配置（全部）
     * GET/any /api/game/anteConfig
     * header: token（TokenMiddleware 注入）
     * 返回：dice_ante_config 列表（包含 mult/is_default 等字段）
     */
    public function anteConfig(Request $request): Response
    {
        $configDeptId = $this->resolvePlayerConfigDeptIdFromRequest($request);
        $anteConfigModel = new DiceAnteConfig();
        $rows = $anteConfigModel->where('dept_id', $configDeptId)->order('id', 'asc')->select()->toArray();
        return $this->success($rows);
    }

    /**
     * 开始游戏（抽奖一局）
     * POST /api/game/playStart
     * header: token（由 TokenMiddleware 注入 request->player_id）
     * body: direction 必传，0=无 1=中奖
     */
    public function playStart(Request $request): Response
    {
        $userId = (int) ($request->player_id ?? 0);
        $direction = $request->post('direction');
        if ($direction !== null) {
            $direction = (int) $direction;
        }
        $ante = $request->post('ante');
        if ($ante !== null) {
            $ante = (int) $ante;
        }
        if (!in_array($direction, [0, 1], true)) {
            return $this->fail('direction must be 0 or 1', ReturnCode::PARAMS_ERROR);
        }
        if (!is_int($ante) || $ante <= 0) {
            return $this->fail('ante must be a positive integer', ReturnCode::PARAMS_ERROR);
        }

        $player = DicePlayer::find($userId);
        if (!$player) {
            return $this->fail('User not found', ReturnCode::NOT_FOUND);
        }

        $lockName = 'play_start_' . $userId;
        $lockResult = Db::query('SELECT GET_LOCK(?, 30) as l', [$lockName]);
        if (empty($lockResult) || (int) ($lockResult[0]['l'] ?? 0) !== 1) {
            return $this->fail('too many requests, please try again later', ReturnCode::BUSINESS_ERROR);
        }
        try {
            $logic = new PlayStartLogic();
            $data = $logic->run($userId, (int) $direction, $ante);

            $lang = $request->header('lang', 'zh');
            if (!is_string($lang) || $lang === '') {
                $lang = 'zh';
            }
            $langLower = strtolower($lang);
            $isEn = $langLower === 'en' || str_starts_with($langLower, 'en-');

            if (is_array($data)) {
                $rewardTier = array_key_exists('reward_tier', $data) ? (string) ($data['reward_tier'] ?? '') : '';
                $targetIndex = array_key_exists('target_index', $data) ? (int) ($data['target_index'] ?? 0) : 0;
                if ($rewardTier !== 'BIGWIN' && $targetIndex > 0) {
                    $configDeptId = AdminScopeHelper::resolvePlayerConfigDeptId($player);
                    $configRow = DiceRewardConfig::getCachedById($targetIndex, $configDeptId);
                    if ($configRow !== null) {
                        $uiText = '';
                        $uiTextEn = '';
                        if (array_key_exists('ui_text', $configRow) && $configRow['ui_text'] !== null) {
                            $uiText = (string) $configRow['ui_text'];
                        }
                        if (array_key_exists('ui_text_en', $configRow) && $configRow['ui_text_en'] !== null) {
                            $uiTextEn = (string) $configRow['ui_text_en'];
                        }
                        if ($isEn && $uiTextEn !== '') {
                            $data['ui_text'] = $uiTextEn;
                        } else {
                            $data['ui_text'] = $uiText;
                        }
                        $data['ui_text_en'] = $uiTextEn;
                    }
                }
            }
            $data['tier'] = $data['reward_tier'] ?? '';

            return $this->success($data);
        } catch (ApiException $e) {
            return $this->fail($e->getMessage(), ReturnCode::BUSINESS_ERROR);
        } catch (\Throwable $e) {
            // 记录抽奖逻辑抛出的真实异常，便于排查“服务超时，没有原因”
            Log::error('playStart 异常: ' . $e->getMessage(), [
                'file' => $e->getFile(),
                'line' => $e->getLine(),
                'trace' => $e->getTraceAsString(),
                'player_id' => $userId,
                'direction' => $direction,
            ]);
            $timeoutRecord = null;
            $timeout_message = '';
            $adminId = null;
            $timeoutDeptId = null;
            try {
                $timeoutPlayer = DicePlayer::find($userId);
                $adminId = ($timeoutPlayer && ($timeoutPlayer->admin_id ?? null)) ? (int) $timeoutPlayer->admin_id : null;
                if ($timeoutPlayer && isset($timeoutPlayer->dept_id) && $timeoutPlayer->dept_id !== null && $timeoutPlayer->dept_id !== '') {
                    $timeoutDeptId = (int) $timeoutPlayer->dept_id;
                }
            } catch (\Throwable $_) {
            }
            try {
                $timeoutRecord = DicePlayRecord::create([
                    'player_id'          => $userId,
                    'dept_id'            => $timeoutDeptId,
                    'admin_id'           => $adminId,
                    'lottery_config_id'  => 0,
                    'lottery_type'       => 0,
                    'is_win'             => 0,
                    'win_coin'           => 0,
                    'super_win_coin'     => 0,
                    'reward_win_coin'    => 0,
                    'direction'          => $direction,
                    'reward_tier'        => '',
                    'start_index'        => 0,
                    'target_index'       => 0,
                    'roll_array'         => '[]',
                    'roll_number'        => 0,
                    'status'             => PlayStartLogic::RECORD_STATUS_TIMEOUT,
                ]);
            } catch (\Exception $inner) {
                $timeout_message = $inner->getMessage();
                Log::error('游玩记录写入超时: ' . $inner->getMessage());
            }
            $payload = $timeoutRecord ? ['record' => $timeoutRecord->toArray()] : [];
            $msg = $timeout_message !== '' ? $timeout_message : $e->getMessage();
            if ($msg === '') {
                $msg = '没有原因';
            }
            return $this->fail('Service timeout: ' . $msg);
        } finally {
            Db::execute('SELECT RELEASE_LOCK(?)', [$lockName]);
        }
    }

    /**
     * 从 token 注入的 player_id 解析所属渠道配置 ID
     */
    private function resolvePlayerConfigDeptIdFromRequest(Request $request): int
    {
        $userId = (int) ($request->player_id ?? 0);
        if ($userId <= 0) {
            return AdminScopeHelper::DEFAULT_TEMPLATE_DEPT;
        }
        $player = DicePlayer::find($userId);
        if (!$player) {
            return AdminScopeHelper::DEFAULT_TEMPLATE_DEPT;
        }
        return AdminScopeHelper::resolvePlayerConfigDeptId($player);
    }
}
