<?php

declare(strict_types=1);

namespace App\Support;

use App\Models\Player;
use App\Models\Currency;
use Illuminate\Http\Request;
use App\Services\LotterySettings;

/**
 * 币种码解析工具。
 *
 * 统一处理 Query/Body 中的 currency 参数，支持回退到玩家默认币种或全局配置。
 */
final class CurrencyResolver
{
    /**
     * 从请求或玩家/配置回退解析币种码。
     *
     * @param  Request  $request  请求对象
     * @param  Player|null  $player  玩家对象（用于回退）
     * @param  string  $key  参数名（默认 currency）
     * @param  string|null  $default  默认币种码（不传则使用 player->default_currency 或 config）
     */
    public static function resolve(
        Request $request,
        ?Player $player = null,
        string $key = 'currency',
        ?string $default = null,
    ): string {
        $raw = $request->input($key) ?? $request->query($key);

        if (is_string($raw) && $raw !== '') {
            $code = strtoupper(substr(trim($raw), 0, 16));
        } else {
            $fallback = $default
                ?? $player?->default_currency
                ?? LotterySettings::defaultCurrency();
            $code = strtoupper(substr(trim((string) $fallback), 0, 16));
        }

        return $code;
    }

    /**
     * 验证币种码格式是否合法。
     *
     * 合法格式：1-16 位字母数字，全大写。
     */
    public static function isValid(string $code): bool
    {
        return preg_match('/^[A-Z0-9]{1,16}$/', $code) === 1;
    }

    /**
     * 币种是否已配置于主数据表。
     */
    public static function exists(string $code): bool
    {
        return self::isValid($code)
            && Currency::query()->where('code', strtoupper($code))->exists();
    }

    /**
     * 币种是否处于启用状态。
     */
    public static function isEnabled(string $code): bool
    {
        return self::isValid($code)
            && Currency::query()
                ->where('code', strtoupper($code))
                ->where('is_enabled', true)
                ->exists();
    }

    /**
     * 解析并验证币种码，无效时返回 null。
     */
    public static function resolveOrNull(
        Request $request,
        ?Player $player = null,
        string $key = 'currency',
        ?string $default = null,
    ): ?string {
        $code = self::resolve($request, $player, $key, $default);

        return self::isValid($code) ? $code : null;
    }
}
