<?php

namespace app\admin\controller\config;

use app\common\controller\Backend;
use app\common\library\game\DepositChannel;
use app\common\library\game\DepositTier;
use app\common\library\game\FinanceCashierConfig;
use app\common\library\game\StreakWinReward;
use app\common\library\game\ZiHuaDictionary as ZiHuaDictionaryLib;
use app\common\service\GameHotDataCoordinator;
use support\think\Db;
use support\Response;
use Webman\Http\Request as WebmanRequest;

/**
 * 游戏配置（game_config）
 */
class GameConfig extends Backend
{
    protected ?object $model = null;

    protected string|array $preExcludeFields = ['id', 'create_time', 'update_time'];

    protected string|array $quickSearchField = ['id', 'config_key', 'remark'];

    protected string|array $defaultSortField = ['id' => 'asc'];

    protected string|array $orderGuarantee = ['id' => 'asc'];

    protected bool $modelValidate = true;

    protected bool $modelSceneValidate = true;

    protected function initController(WebmanRequest $request): ?Response
    {
        $this->model = new \app\common\model\GameConfig();
        return null;
    }

    /**
     * @return list<string>
     */
    protected function excludedConfigKeys(): array
    {
        return [
            ZiHuaDictionaryLib::CONFIG_KEY,
            DepositTier::CONFIG_KEY,
            DepositChannel::CONFIG_KEY,
            FinanceCashierConfig::CONFIG_KEY,
            StreakWinReward::CONFIG_KEY,
        ];
    }

    /**
     * @return list<string>
     */
    protected function formExcludedKeys(): array
    {
        return [
            'period_auto_create_enabled',
            'period_manual_create_enabled',
        ];
    }

    /**
     * 列表：排除独立表单维护的配置键
     */
    protected function _index(): Response
    {
        if ($this->request && $this->request->get('select')) {
            return $this->select($this->request);
        }

        list($where, $alias, $limit, $order) = $this->queryBuilder();
        $table = strtolower($this->model->getTable());
        $mainShort = $alias[$table] ?? '';
        if ($mainShort !== '') {
            $where[] = [$mainShort . '.config_key', 'not in', $this->excludedConfigKeys()];
        }

        $res = $this->model
            ->field($this->indexField)
            ->withJoin($this->withJoinTable, $this->withJoinType)
            ->with($this->withJoinTable)
            ->alias($alias)
            ->where($where)
            ->order($order)
            ->paginate($limit);

        return $this->success('', [
            'list'   => $res->items(),
            'total'  => $res->total(),
            'remark' => get_route_remark(),
        ]);
    }

    /**
     * 远程下拉：排除独立维护的配置键
     */
    protected function _select(): Response
    {
        if (empty($this->model)) {
            return $this->success('', [
                'list'  => [],
                'total' => 0,
            ]);
        }

        $pk = $this->model->getPk();

        $fields = [$pk];
        $quickSearchArr = is_array($this->quickSearchField) ? $this->quickSearchField : explode(',', (string) $this->quickSearchField);
        foreach ($quickSearchArr as $f) {
            $f = trim((string) $f);
            if ($f === '') {
                continue;
            }
            $f = str_contains($f, '.') ? substr($f, strrpos($f, '.') + 1) : $f;
            if ($f !== '' && !in_array($f, $fields, true)) {
                $fields[] = $f;
            }
        }

        list($where, $alias, $limit, $order) = $this->queryBuilder();
        $table = strtolower($this->model->getTable());
        $mainShort = $alias[$table] ?? '';
        if ($mainShort !== '') {
            $where[] = [$mainShort . '.config_key', 'not in', $this->excludedConfigKeys()];
        }

        $res = $this->model
            ->field($fields)
            ->alias($alias)
            ->where($where)
            ->order($order)
            ->paginate($limit);

        return $this->success('', [
            'list'  => $res->items(),
            'total' => $res->total(),
        ]);
    }

    /**
     * 表单批量保存：一次提交当前页面全部配置
     */
    public function save(WebmanRequest $request): Response
    {
        $response = $this->initializeBackend($request);
        if ($response !== null) {
            return $response;
        }
        if ($request->method() !== 'POST') {
            return $this->error(__('Parameter error'));
        }

        $payload = $request->post();
        if (!is_array($payload)) {
            return $this->error(__('Parameter error'));
        }

        $items = $payload['items'] ?? null;
        if (!is_array($items)) {
            return $this->error(__('Parameter error'));
        }

        $exclude = array_merge($this->excludedConfigKeys(), $this->formExcludedKeys());
        $rows = Db::name('game_config')
            ->whereNotIn('config_key', $exclude)
            ->field(['id', 'config_key', 'value_type'])
            ->select()
            ->toArray();

        if ($rows === []) {
            return $this->success(__('Operation completed'));
        }

        $allowMap = [];
        foreach ($rows as $row) {
            if (!isset($row['config_key']) || !is_string($row['config_key']) || $row['config_key'] === '') {
                continue;
            }
            $allowMap[$row['config_key']] = $row;
        }

        $now = time();
        $updatedKeys = [];
        Db::startTrans();
        try {
            foreach ($items as $configKey => $configValue) {
                if (!is_string($configKey) || $configKey === '' || !isset($allowMap[$configKey])) {
                    continue;
                }

                $valueType = isset($allowMap[$configKey]['value_type']) && is_string($allowMap[$configKey]['value_type'])
                    ? $allowMap[$configKey]['value_type']
                    : 'string';

                $persistValue = $configValue;
                if (is_array($persistValue)) {
                    if ($valueType === 'json') {
                        $persistValue = json_encode($persistValue, JSON_UNESCAPED_UNICODE);
                    } else {
                        $persistValue = '';
                    }
                }
                if ($persistValue === null) {
                    $persistValue = '';
                }

                Db::name('game_config')->where('id', $allowMap[$configKey]['id'])->update([
                    'config_value' => (string) $persistValue,
                    'update_time'  => $now,
                ]);
                $updatedKeys[] = $configKey;
            }
            Db::commit();
        } catch (\Throwable $e) {
            Db::rollback();
            return $this->error($e->getMessage());
        }

        foreach (array_values(array_unique($updatedKeys)) as $key) {
            GameHotDataCoordinator::afterGameConfigKeyCommitted($key);
        }

        return $this->success(__('Operation completed'));
    }
}
