<?php

declare(strict_types=1);

/**
 * 本文件属于 DBErp 进销存系统。
 *
 * 版权所有 © 2026 北京珑大钜商科技有限公司。保留所有权利。
 *
 * 未经官方授权，不得删除、篡改或隐藏本文件中的版权声明、产品标识与来源信息。
 * 商业授权、官方更新与技术支持服务，请以珑大官方支持中心记录为准。
 *
 * @link https://support.loongdom.cn
 * @see  https://www.dberp.com.cn
 */

namespace App\Support;

use App\Models\DberpSystemProfile;
use Illuminate\Support\Facades\Schema;

/**
 * 系统档案中的展示类参数（时区、默认货币、金额/数量小数位）统一读取入口。
 */
final class DberpSystemProfileSettings
{
    public static function displayTimezone(): string
    {
        return once(function (): string {
            $fromProfile = self::readProfileColumn('display_timezone');

            if (is_string($fromProfile) && in_array($fromProfile, timezone_identifiers_list(), true)) {
                return $fromProfile;
            }

            $configured = (string) config('app.display_timezone', 'UTC');

            return in_array($configured, timezone_identifiers_list(), true) ? $configured : 'UTC';
        });
    }

    public static function defaultCurrencyCode(): string
    {
        return once(function (): string {
            $fromProfile = self::readProfileColumn('default_currency_code');

            if (is_string($fromProfile)) {
                $normalized = DberpCurrencySelectOptions::normalizeCode($fromProfile);

                if ($normalized !== null) {
                    return $normalized;
                }
            }

            return DberpCurrencySelectOptions::configuredDefaultCode();
        });
    }

    public static function amountDecimalPlaces(): int
    {
        return self::displayDecimals()['amount'];
    }

    public static function quantityDecimalPlaces(): int
    {
        return self::displayDecimals()['quantity'];
    }

    /**
     * @return array{amount: int, quantity: int}
     */
    private static function displayDecimals(): array
    {
        return once(function (): array {
            $fallbackAmount = self::configPrecision('amount', 2);
            $fallbackQuantity = self::configPrecision('quantity', 2);

            try {
                $table = (new DberpSystemProfile)->getTable();

                if (Schema::hasTable($table)) {
                    $profile = DberpSystemProfile::query()->first([
                        'amount_decimal_places',
                        'quantity_decimal_places',
                    ]);

                    if ($profile !== null) {
                        return [
                            'amount' => self::clampDecimals((int) $profile->amount_decimal_places),
                            'quantity' => self::clampDecimals((int) $profile->quantity_decimal_places),
                        ];
                    }
                }
            } catch (\Throwable) {
            }

            return [
                'amount' => $fallbackAmount,
                'quantity' => $fallbackQuantity,
            ];
        });
    }

    private static function readProfileColumn(string $column): mixed
    {
        try {
            $table = (new DberpSystemProfile)->getTable();

            if (! Schema::hasTable($table) || ! Schema::hasColumn($table, $column)) {
                return null;
            }

            return DberpSystemProfile::query()->value($column);
        } catch (\Throwable) {
            return null;
        }
    }

    private static function configPrecision(string $key, int $default): int
    {
        /** @var array<string, int|string>|null $map */
        $map = config('dberp.number_precision');
        /** @var int|string|null $raw */
        $raw = \is_array($map) ? ($map[$key] ?? null) : null;

        if ($raw === null || $raw === '') {
            return $default;
        }

        return self::clampDecimals((int) $raw);
    }

    private static function clampDecimals(int $decimals): int
    {
        return max(0, min(12, $decimals));
    }
}
