<?php

declare(strict_types=1);

namespace App\Support;

use App\Models\DberpProduct;
use App\Models\DberpUnit;
use Filament\Schemas\Components\Utilities\Get;

/**
 * 商品辅助计量「换算关系」展示文案（仅 UI，不参与数量运算）。
 */
final class DberpProductAuxiliaryUnitPreview
{
    /**
     * 根据 Filament 表单当前状态生成预览，例如「1 箱 = 24 瓶」。
     */
    public static function fromFormGet(Get $get): string
    {
        if (! (bool) $get('is_auxiliary_unit_enabled')) {
            return '';
        }

        return self::fromSnapshot(
            (int) ($get('unit_id') ?? 0),
            (int) ($get('auxiliary_unit_id') ?? 0),
            $get('auxiliary_unit_quantity'),
            $get('base_unit_quantity'),
        );
    }

    /**
     * 根据已保存商品生成预览；未启用或信息不全时返回空字符串。
     */
    public static function fromProduct(DberpProduct $product): string
    {
        if (! (bool) $product->is_auxiliary_unit_enabled) {
            return '';
        }

        return self::fromSnapshot(
            (int) $product->unit_id,
            (int) ($product->auxiliary_unit_id ?? 0),
            $product->auxiliary_unit_quantity,
            $product->base_unit_quantity,
        );
    }

    /**
     * 按主单位 ID、辅助单位 ID 与两侧数量快照生成「换算关系」展示（如「1 箱 = 24 瓶」），用于单据/流水等历史快照展示。
     */
    public static function fromSnapshot(
        int $baseUnitId,
        int $auxiliaryUnitId,
        mixed $auxiliaryQuantity,
        mixed $baseQuantity,
    ): string {
        return self::composeLine($baseUnitId, $auxiliaryUnitId, $auxiliaryQuantity, $baseQuantity);
    }

    private static function composeLine(int $baseUnitId, int $auxiliaryUnitId, mixed $auxiliaryQuantity, mixed $baseQuantity): string
    {
        if ($baseUnitId <= 0 || $auxiliaryUnitId <= 0) {
            return '';
        }

        $auxiliaryString = self::normalizeNumericString($auxiliaryQuantity);
        $baseString = self::normalizeNumericString($baseQuantity);

        if ($auxiliaryString === null || $baseString === null) {
            return '';
        }

        if (bccomp($auxiliaryString, '0', 6) !== 1 || bccomp($baseString, '0', 6) !== 1) {
            return '';
        }

        $names = DberpUnit::query()
            ->whereIn('id', [$baseUnitId, $auxiliaryUnitId])
            ->pluck('name', 'id');

        $baseName = trim((string) ($names[$baseUnitId] ?? ''));
        $auxiliaryName = trim((string) ($names[$auxiliaryUnitId] ?? ''));

        if ($baseName === '' || $auxiliaryName === '') {
            return '';
        }

        return sprintf(
            '%s %s = %s %s',
            self::trimDecimalZeros($auxiliaryString),
            $auxiliaryName,
            self::trimDecimalZeros($baseString),
            $baseName,
        );
    }

    private static function normalizeNumericString(mixed $value): ?string
    {
        if ($value === null || $value === '') {
            return null;
        }

        $string = is_string($value) ? trim($value) : trim((string) $value);

        if ($string === '' || ! is_numeric($string)) {
            return null;
        }

        return $string;
    }

    private static function trimDecimalZeros(string $numeric): string
    {
        if (str_contains($numeric, 'e') || str_contains($numeric, 'E')) {
            $numeric = rtrim(rtrim(sprintf('%.6F', (float) $numeric), '0'), '.');
        }

        if (! str_contains($numeric, '.')) {
            return $numeric;
        }

        return rtrim(rtrim($numeric, '0'), '.');
    }
}
