<?php

declare(strict_types=1);

namespace App\Support;

use App\Business\Inventory\InventorySerialNumberService;
use Closure;
use Filament\Forms\Components\Field;
use Filament\Forms\Components\TagsInput;
use Filament\Forms\Components\Textarea;
use Filament\Schemas\Components\Utilities\Get;
use Filament\Schemas\Components\Utilities\Set;

/**
 * 入库类单据明细：手工录入新序列号（支持逐个标签、逗号分隔与批量粘贴）。
 *
 * NOTE: 入库登记的是尚未入账的新序列号，不提供「在库序列号」点选（该能力仅用于出库扣减）。
 */
final class DberpDocumentLineInboundSerialNumberFormFields
{
    public const BULK_PASTE_FIELD = '_inbound_serial_bulk_paste';

    /**
     * @return list<Field>
     */
    public static function inboundSerialNumberFields(
        Closure $resolveProduct,
        string $quantityField,
        string $tagsLabel = 'dberp.fields.serial_numbers',
    ): array {
        return [
            self::bulkPasteTextarea($resolveProduct, $quantityField),
            self::serialNumbersTagsInput($resolveProduct, $quantityField, $tagsLabel),
        ];
    }

    private static function bulkPasteTextarea(Closure $resolveProduct, string $quantityField): Textarea
    {
        return DberpProductInventoryRefinementFormFields::constrainSerialField(
            Textarea::make(self::BULK_PASTE_FIELD)
                ->label(__('dberp.document_line.bulk_paste_serial_numbers'))
                ->helperText(__('dberp.document_line.bulk_paste_serial_numbers_helper'))
                ->rows(3)
                ->dehydrated(false)
                ->placeholder(__('dberp.document_line.bulk_paste_serial_numbers_placeholder'))
                ->live(debounce: 500)
                ->afterStateUpdated(function (?string $state, Set $set, Get $get) use ($resolveProduct, $quantityField): void {
                    if (blank($state)) {
                        return;
                    }

                    $product = $resolveProduct($get);

                    if (! DberpProductInventoryRefinementFormFields::productManagesSerial($product)) {
                        return;
                    }

                    $parsed = app(InventorySerialNumberService::class)->normalizeSerialNumbers($state);

                    if ($parsed === []) {
                        return;
                    }

                    $maxCount = DberpDocumentLineSerialNumberFormFields::maxSerialCountForQuantity(
                        $resolveProduct,
                        $quantityField,
                    )($get);

                    $merged = DberpDocumentLineSerialNumberFormFields::trimSerialsToMaxCount(
                        array_merge($get('serial_numbers') ?? [], $parsed),
                        $maxCount,
                    );

                    $set('serial_numbers', $merged);
                    $set(self::BULK_PASTE_FIELD, null);
                })
                ->columnSpanFull(),
            $resolveProduct,
        );
    }

    private static function serialNumbersTagsInput(
        Closure $resolveProduct,
        string $quantityField,
        string $tagsLabel,
    ): TagsInput {
        return DberpProductInventoryRefinementFormFields::constrainSerialField(
            DberpDocumentLineSerialNumberFormFields::configureTagsInput(
                TagsInput::make('serial_numbers')
                    ->label(__($tagsLabel))
                    ->helperText(__('dberp.document_line.inbound_serial_numbers_helper'))
                    ->separator(',')
                    ->splitKeys(['Enter', 'Tab'])
                    ->columnSpanFull(),
                $resolveProduct,
                $quantityField,
            ),
            $resolveProduct,
        );
    }
}
