<?php

declare(strict_types=1);

namespace app\admin\controller\config;

use app\common\controller\Backend;
use app\common\library\game\StreakWinReward as StreakWinRewardLib;
use app\common\service\GameHotDataCoordinator;
use app\common\service\GameHotDataLock;
use support\think\Db;
use support\Response;
use Throwable;
use Webman\Http\Request as WebmanRequest;

/**
 * 连胜奖励（game_config.streak_win_reward）
 */
class StreakWinReward extends Backend
{
    protected bool $modelValidate = false;

    protected array $noNeedPermission = ['index', 'save'];

    private function hasNodePermission(WebmanRequest $request, string $action): bool
    {
        if (!$this->auth) {
            return false;
        }
        $controllerPath = get_controller_path($request);
        if (!$controllerPath) {
            return false;
        }
        $paths = [];
        $paths[] = $controllerPath . '/' . $action;
        $parts = explode('/', $controllerPath);
        foreach ($parts as &$part) {
            if (str_contains($part, '_')) {
                $part = lcfirst(str_replace(' ', '', ucwords(str_replace('_', ' ', $part))));
            }
        }
        $paths[] = implode('/', $parts) . '/' . $action;
        foreach (array_values(array_unique($paths)) as $path) {
            if ($this->auth->check($path)) {
                return true;
            }
        }

        return false;
    }

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

    public function index(WebmanRequest $request): Response
    {
        $response = $this->initializeBackend($request);
        if ($response !== null) {
            return $response;
        }
        if (!$this->hasNodePermission($request, 'index')) {
            return $this->error(__('You have no permission'), [], 401);
        }
        if ($request->method() !== 'GET') {
            return $this->error(__('Parameter error'));
        }
        $row = Db::name('game_config')->where('config_key', StreakWinRewardLib::CONFIG_KEY)->find();
        $rows = StreakWinRewardLib::parseFromConfigValue($row['config_value'] ?? null);

        return $this->success('', [
            'rows' => $rows,
        ]);
    }

    public function save(WebmanRequest $request): Response
    {
        $response = $this->initializeBackend($request);
        if ($response !== null) {
            return $response;
        }
        if (!$this->hasNodePermission($request, 'save')) {
            return $this->error(__('You have no permission'), [], 401);
        }
        if ($request->method() !== 'POST') {
            return $this->error(__('Parameter error'));
        }
        $payload = $request->post('rows');
        if (!is_array($payload)) {
            return $this->error(__('Invalid parameters'));
        }
        $encoded = StreakWinRewardLib::encodeForDb($payload);
        $now = time();
        $resourceKey = GameHotDataLock::safeResourceKeyForConfig(StreakWinRewardLib::CONFIG_KEY);
        $lock = GameHotDataLock::tryAcquire(GameHotDataLock::TYPE_GAME_CONFIG, $resourceKey);
        if (!$lock['acquired']) {
            return $this->error(__('This config is locked by another operation, please try again later'));
        }
        try {
            Db::startTrans();
            try {
                $exists = Db::name('game_config')->where('config_key', StreakWinRewardLib::CONFIG_KEY)->find();
                if ($exists) {
                    Db::name('game_config')->where('config_key', StreakWinRewardLib::CONFIG_KEY)->update([
                        'config_value' => $encoded,
                        'update_time'  => $now,
                    ]);
                } else {
                    Db::name('game_config')->insert([
                        'config_key'   => StreakWinRewardLib::CONFIG_KEY,
                        'config_value' => $encoded,
                        'value_type'   => 'json',
                        'remark'       => '连胜奖励',
                        'create_time'  => $now,
                        'update_time'  => $now,
                    ]);
                }
                Db::commit();
            } catch (Throwable $e) {
                Db::rollback();

                return $this->error($e->getMessage());
            }
            StreakWinRewardLib::clearCache();
            GameHotDataCoordinator::afterGameConfigKeyCommitted(StreakWinRewardLib::CONFIG_KEY);

            return $this->success(__('Saved successfully'));
        } finally {
            GameHotDataLock::release(GameHotDataLock::TYPE_GAME_CONFIG, $resourceKey, $lock['token'], $lock['redis_lock']);
        }
    }
}
