<?php

declare(strict_types=1);

namespace App\Support;

use App\Models\Currency;
use App\Services\LotterySettings;

/**
 * 信用占成盘额度（代理/玩家授信、已用）在库内按「主货币整数」存储；
 * 彩票下注、钱包 API 使用最小货币单位（minor）。本类负责二者换算。
 */
final class CreditAmountScale
{
    public static function minorUnitFactor(string $currencyCode): int
    {
        $code = strtoupper(trim($currencyCode));
        if ($code === '') {
            return (int) max(1, 10 ** LotterySettings::currencyDisplayDecimals());
        }

        $currency = Currency::query()->where('code', $code)->first();
        $decimals = $currency !== null
            ? (int) $currency->decimal_places
            : LotterySettings::currencyDisplayDecimals();

        return (int) max(1, 10 ** max(0, min(12, $decimals)));
    }

    public static function majorToMinor(int $major, string $currencyCode): int
    {
        // 负值防御：所有调用方都应在传入前 max(0, ...) 兜底（available credit / balance / 等），
        // 此处 double-check 是兜底而非业务逻辑。若发生负数通常意味着上游计算 bug，
        // 记录 warning 让 production 暴露问题而不被静默吞掉。
        if ($major < 0) {
            \Illuminate\Support\Facades\Log::warning('CreditAmountScale::majorToMinor received negative value', [
                'major' => $major,
                'currency_code' => $currencyCode,
                'trace' => debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 4),
            ]);

            return 0;
        }

        return $major * self::minorUnitFactor($currencyCode);
    }

    /**
     * 最小单位 → 主货币整数（占用授信时向上取整，与 preflight 按 major 校验一致）。
     */
    public static function minorToMajor(int $minor, string $currencyCode): int
    {
        $factor = self::minorUnitFactor($currencyCode);
        if ($factor <= 1) {
            return $minor;
        }

        if ($minor <= 0) {
            return 0;
        }

        return intdiv($minor + $factor - 1, $factor);
    }
}
