<?php

declare(strict_types=1);

namespace App\Support;

use App\Business\Inventory\InventoryDocumentLineHintService;
use Closure;
use Filament\Forms\Components\Placeholder;
use Filament\Schemas\Components\Utilities\Get;

/**
 * 库存类单据明细：账面/可用库存参考提示（只读，不写入明细字段）。
 */
final class DberpDocumentLineInventoryHintFormFields
{
    /**
     * 盘点录入：参考账面数量（与过账前库存余额汇总口径一致）。
     */
    public static function stocktakeBookQuantityPlaceholder(Closure $resolveWarehouseId): Placeholder
    {
        return self::inventoryHintPlaceholder(
            name: '_document_line_stocktake_book_hint',
            label: __('dberp.fields.book_quantity'),
            resolveWarehouseId: $resolveWarehouseId,
            hintResolver: static fn (InventoryDocumentLineHintService $service, int $warehouseId, int $productId, int $productSkuId): ?string => $service->formattedBookQuantityHintForLine(
                $warehouseId,
                $productId,
                $productSkuId,
            ),
            visibleWhen: static fn (InventoryDocumentLineHintService $service, int $warehouseId, int $productId, int $productSkuId): bool => $warehouseId > 0
                && $productId > 0
                && $service->resolveProductSkuIdForInventoryHint($productId, $productSkuId) !== null,
        );
    }

    /**
     * 调拨/其他出库等：参考可用库存（出库仓）。
     */
    public static function availableStockPlaceholder(Closure $resolveWarehouseId): Placeholder
    {
        return self::inventoryHintPlaceholder(
            name: '_document_line_available_stock_hint',
            resolveWarehouseId: $resolveWarehouseId,
            hintResolver: static fn (InventoryDocumentLineHintService $service, int $warehouseId, int $productId, int $productSkuId): ?string => $service->formattedAvailableStockHint(
                $warehouseId,
                $productId,
                $productSkuId,
            ),
        );
    }

    /**
     * @param  Closure(InventoryDocumentLineHintService, int, int, int): (?string)  $hintResolver
     */
    private static function inventoryHintPlaceholder(
        string $name,
        Closure $resolveWarehouseId,
        Closure $hintResolver,
        string $productIdField = 'product_id',
        string $productSkuIdField = 'product_sku_id',
        ?string $label = null,
        ?Closure $visibleWhen = null,
    ): Placeholder {
        return Placeholder::make($name)
            ->label($label ?? __('dberp.document_line.inventory_hint_reference'))
            ->content(function (Get $get) use ($resolveWarehouseId, $hintResolver, $productIdField, $productSkuIdField): string {
                $warehouseId = (int) $resolveWarehouseId();
                $productId = (int) ($get($productIdField) ?? 0);
                $productSkuId = (int) ($get($productSkuIdField) ?? 0);

                return $hintResolver(
                    app(InventoryDocumentLineHintService::class),
                    $warehouseId,
                    $productId,
                    $productSkuId,
                ) ?? '';
            })
            ->visible(function (Get $get) use ($resolveWarehouseId, $hintResolver, $productIdField, $productSkuIdField, $visibleWhen): bool {
                $warehouseId = (int) $resolveWarehouseId();
                $productId = (int) ($get($productIdField) ?? 0);
                $productSkuId = (int) ($get($productSkuIdField) ?? 0);

                if ($warehouseId <= 0 || $productId <= 0) {
                    return false;
                }

                $service = app(InventoryDocumentLineHintService::class);

                if ($visibleWhen !== null && ! $visibleWhen($service, $warehouseId, $productId, $productSkuId)) {
                    return false;
                }

                $hint = $hintResolver($service, $warehouseId, $productId, $productSkuId);

                return $hint !== null && trim($hint) !== '';
            })
            ->columnSpanFull();
    }
}
