<?php

namespace App\Filament\Support;

use App\Models\Catalog\Product;
use Closure;
use Filament\Actions\Action;
use Filament\Forms\Components\Select;

/**
 * The product picker used in every repeater line item and stand-alone
 * product field across the app (invoices, GRNs, returns, purchase orders,
 * stock movements, barcode labels, bundles, …).
 *
 * A thin wrapper over {@see RelationSelect}, differing only in the columns a
 * search matches: **name, SKU and barcode**, not name alone. A barcode
 * scanner types a code into whichever product field has focus exactly as a
 * keyboard would — it is Filament's own searchable-select handling that then
 * finds the match and lets the operator (or a unique match) confirm it, so
 * scanning a product here needs no scan-specific JS at all, only a search
 * that actually looks at the columns a scan produces.
 *
 * Every caller keeps its own `$modifyQueryUsing` scoping exactly as it was —
 * a GRN's category filter, a Return's "only what this customer bought" —
 * since this passes it straight through to {@see RelationSelect::standalone()}
 * unchanged.
 */
class ProductSelect
{
    private const SEARCH_COLUMNS = ['name', 'sku', 'barcode'];

    /**
     * @param  array<int, \Filament\Schemas\Components\Component>  $createForm
     */
    public static function standalone(
        string $name = 'product_id',
        ?Closure $modifyQueryUsing = null,
        array $createForm = [],
        ?string $createPermission = null,
    ): Select {
        return RelationSelect::standalone(
            name: $name,
            modelClass: Product::class,
            titleAttribute: 'name',
            modifyQueryUsing: $modifyQueryUsing,
            createForm: $createForm,
            createPermission: $createPermission,
            searchColumns: self::SEARCH_COLUMNS,
        )->searchPrompt('Search by name, SKU or barcode — or scan…');
    }

    /**
     * The `->relationship()`-bound flavour, for a field that sits directly on
     * an Eloquent form (not inside an unbound Repeater row) — see
     * {@see RelationSelect::make()}.
     *
     * @param  array<int, \Filament\Schemas\Components\Component>  $createForm
     */
    public static function make(
        string $name = 'product_id',
        string $relationship = 'product',
        array $createForm = [],
        ?string $createPermission = null,
        ?Closure $modifyQueryUsing = null,
    ): Select {
        return RelationSelect::make(
            name: $name,
            relationship: $relationship,
            titleAttribute: 'name',
            createForm: $createForm,
            createPermission: $createPermission,
            modifyQueryUsing: $modifyQueryUsing,
            searchColumns: self::SEARCH_COLUMNS,
        )->searchPrompt('Search by name, SKU or barcode — or scan…');
    }

    /**
     * For a `->relationship()->multiple()` select (Deal's target products) —
     * Select::searchable() takes the column list directly and there is no
     * RelationSelect wrapper for the multiple case to route through.
     *
     * @return array<int, string>
     */
    public static function searchColumns(): array
    {
        return self::SEARCH_COLUMNS;
    }
}
