<?php

namespace app\admin\controller\game;

use app\common\controller\Backend;
use app\common\library\admin\WebSocketConfigHelper;
use app\common\service\GameLiveService;
use app\common\service\GameRecordService;
use support\Response;
use Webman\Http\Request as WebmanRequest;

/**
 * Game live control.
 */
class Live extends Backend
{
    protected ?object $model = null;

    protected function initController(WebmanRequest $request): ?Response
    {
        return null;
    }

    protected function _index(): Response
    {
        $recordIdRaw = $this->request ? $this->request->get('record_id') : null;
        $recordId = is_numeric((string) $recordIdRaw) ? (int) $recordIdRaw : null;
        return $this->success('', GameLiveService::buildSnapshot($recordId));
    }

    public function snapshot(WebmanRequest $request): Response
    {
        $response = $this->initializeBackend($request);
        if ($response !== null) {
            return $response;
        }
        $recordIdRaw = $request->get('record_id');
        $recordId = is_numeric((string) $recordIdRaw) ? (int) $recordIdRaw : null;
        return $this->success('', GameLiveService::buildSnapshot($recordId));
    }

    /**
     * WebSocket config for admin live page.
     */
    public function wsConfig(WebmanRequest $request): Response
    {
        $response = $this->initializeBackend($request);
        if ($response !== null) {
            return $response;
        }

        $topics = [
            'admin.live.snapshot',
            'admin.live.opened',
            'jackpot.hit',
            'period.tick',
            'period.locked',
            'period.opened',
            'period.payout',
            'bet.accepted',
            'wallet.changed',
            'auto.spin.progress',
        ];

        return $this->success('', [
            'name' => 'ws.admin.live',
            'ws_url' => WebSocketConfigHelper::wsUrl($request),
            'connect_tip' => 'The admin live page auto-subscribes topics for status, draw result and payout events.',
            'subscribe_topics' => $topics,
            'sample_messages' => [
                '{"action":"ping"}',
                '{"action":"subscribe","topics":["admin.live.snapshot","admin.live.opened"]}',
                '{"action":"subscribe","topics":["period.tick","period.opened","wallet.changed"]}',
            ],
        ]);
    }

    public function calculate(WebmanRequest $request): Response
    {
        $response = $this->initializeBackend($request);
        if ($response !== null) {
            return $response;
        }
        if ($request->method() !== 'POST') {
            return $this->error(__('Parameter error'));
        }
        $recordIdRaw = $request->post('record_id');
        $recordId = is_numeric((string) $recordIdRaw) ? (int) $recordIdRaw : null;
        $manualRaw = $request->post('manual_number');
        $manualNumber = is_numeric((string) $manualRaw) ? (int) $manualRaw : null;
        $res = GameLiveService::calculateResult($recordId, $manualNumber);
        if (!($res['ok'] ?? false)) {
            $errMsg = $res['msg'] ?? null;
            return $this->error(is_string($errMsg) ? $errMsg : __('Calculation failed'));
        }
        $okMsg = $res['msg'] ?? '';
        return $this->success(is_string($okMsg) ? $okMsg : '', $res);
    }

    /**
     * Schedule draw number for current period.
     */
    public function draw(WebmanRequest $request): Response
    {
        $response = $this->initializeBackend($request);
        if ($response !== null) {
            return $response;
        }
        if ($request->method() !== 'POST') {
            return $this->error(__('Parameter error'));
        }
        $recordIdRaw = $request->post('record_id');
        $recordId = is_numeric((string) $recordIdRaw) ? (int) $recordIdRaw : null;
        $manualRaw = $request->post('manual_number');
        if (!is_numeric((string) $manualRaw)) {
            return $this->error(__('Please enter the draw number'));
        }
        $manualNumber = (int) $manualRaw;
        $res = GameLiveService::scheduleDraw($recordId, $manualNumber);
        if (!($res['ok'] ?? false)) {
            $errMsg = $res['msg'] ?? null;
            return $this->error(is_string($errMsg) ? $errMsg : __('Schedule failed'));
        }
        $okMsg = $res['msg'] ?? '';
        return $this->success(is_string($okMsg) ? $okMsg : '', $res);
    }

    /**
     * Runtime switch for game period generation and betting.
     */
    public function runtime(WebmanRequest $request): Response
    {
        $response = $this->initializeBackend($request);
        if ($response !== null) {
            return $response;
        }
        if ($request->method() !== 'POST') {
            return $this->error(__('Parameter error'));
        }
        $raw = $request->post('enabled');
        $enabled = $raw === true || $raw === '1' || $raw === 1;
        GameRecordService::setAutoCreateEnabled($enabled);
        if ($enabled) {
            GameRecordService::bootstrapPeriodWhenRuntimeEnabled();
        }
        return $this->success('', GameLiveService::buildSnapshot(null));
    }

    /**
     * Void current period and refund waiting orders.
     */
    public function voidPeriod(WebmanRequest $request): Response
    {
        $response = $this->initializeBackend($request);
        if ($response !== null) {
            return $response;
        }
        if ($request->method() !== 'POST') {
            return $this->error(__('Parameter error'));
        }
        $recordIdRaw = $request->post('record_id');
        $recordId = is_numeric((string) $recordIdRaw) ? (int) $recordIdRaw : null;
        $voidReason = $request->post('void_reason');
        $reasonStr = is_string($voidReason) ? $voidReason : '';
        $res = GameLiveService::voidCurrentPeriod($recordId, $reasonStr);
        if (!($res['ok'] ?? false)) {
            $errMsg = $res['msg'] ?? null;
            return $this->error(is_string($errMsg) ? $errMsg : __('Void failed'));
        }
        $okMsg = $res['msg'] ?? '';
        $snapshot = GameLiveService::buildSnapshot(null);
        // 作废本局后：必须关闭自动创建下一局开关（允许管理员后续手动重新开启）
        $snapshot['runtime_enabled'] = false;
        // 作废后一般不存在进行中的局，直接进入维护态（用于前端展示“维护中”倒计时）
        $snapshot['maintenance_ui'] = true;
        $refund = $res['refund'] ?? null;
        if (is_array($refund)) {
            $snapshot['void_refund'] = $refund;
        }
        return $this->success(is_string($okMsg) ? $okMsg : '', $snapshot);
    }
}
