<?php

namespace App\Filament\Resources;

use App\Filament\Exports\StockMovementExporter;
use App\Filament\Resources\BinCardResource\Pages\ListBinCard;
use App\Filament\Resources\Concerns\HasModulePermissions;
use App\Filament\Resources\Concerns\HasStandardTableFeatures;
use App\Models\StockMovement;
use App\Support\Quantity;
use Filament\Forms\Components\TextInput;
use Filament\Resources\Resource;
use Filament\Schemas\Schema;
use Filament\Support\Icons\Heroicon;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Enums\FiltersLayout;
use Filament\Tables\Filters\Filter;
use Filament\Tables\Filters\SelectFilter;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;

/**
 * Ported from App\Http\Controllers\Isms\BinCardController
 * (docs/migration-plan.md Phase 4). Read-only append-only ledger — the
 * append-only invariant lives in StockMovementService::record() (already
 * ported and exercised by every other Phase 3/4 resource), not here.
 * Branch filtering comes from StockMovement's own BranchScoped global scope
 * (see App\Models\StockMovement) — no manual filter needed here. CSV export
 * is a header action gated by the separate isms_bin_card.export permission,
 * matching the source's explicit in-controller check.
 */
class BinCardResource extends Resource
{
    use HasModulePermissions;
    use HasStandardTableFeatures;

    protected static ?string $model = StockMovement::class;

    protected static string $permissionModuleKey = 'isms_bin_card';

    protected static string $exporter = StockMovementExporter::class;

    protected static string|\BackedEnum|null $navigationIcon = Heroicon::OutlinedQueueList;

    protected static string|\UnitEnum|null $navigationGroup = 'Reports';

    protected static ?string $navigationLabel = 'Stock Movements Report';

    protected static ?int $navigationSort = 90;

    public static function form(Schema $schema): Schema
    {
        return $schema->components([]);
    }

    public static function table(Table $table): Table
    {
        return static::standardTableDefaults($table)
            ->recordUrl(static::standardRecordUrl())
            ->emptyStateHeading('No stock movements yet')
            ->emptyStateDescription('Every issue and receipt against a product builds its bin card.')
            ->columns([
                TextColumn::make('created_at')->dateTime()->sortable(),
                TextColumn::make('product.name')->label('Product')->searchable(),
                TextColumn::make('branch.name')->label('Branch'),
                TextColumn::make('movementType.name')->label('Type')->badge(),
                TextColumn::make('quantity_change')
                    ->label('Qty Change')
                    ->formatStateUsing(fn ($state, StockMovement $record): string => Quantity::format($state, $record->unit))
                    ->color(fn (StockMovement $record): string => (float) $record->quantity_change >= 0 ? 'success' : 'danger'),
                TextColumn::make('quantity_after')
                    ->label('Qty After')
                    ->formatStateUsing(fn ($state, StockMovement $record): string => Quantity::format($state, $record->unit)),
                TextColumn::make('reference_number')->label('Reference')->placeholder('—'),
                TextColumn::make('creator.name')->label('Recorded By')->placeholder('—'),
            ])
            ->defaultSort('created_at', 'desc')
            ->defaultPaginationPageOption(25)
            ->filters([
                SelectFilter::make('movement_type_id')->label('Movement Type')->relationship('movementType', 'name'),
                SelectFilter::make('product_id')->relationship('product', 'name'),
                Filter::make('reference_number')
                    ->schema([TextInput::make('value')->label('Reference')])
                    ->query(fn (Builder $query, array $data): Builder => $query->when(
                        $data['value'] ?? null,
                        fn (Builder $q, $value) => $q->where('reference_number', 'like', "%{$value}%"),
                    )),
            ])
            ->filtersLayout(FiltersLayout::AboveContentCollapsible)
            ->filtersFormColumns(2)
            ->headerActions(static::standardExportActions())
            ->toolbarActions(static::standardExportBulkActions());
    }

    public static function getPages(): array
    {
        return [
            'index' => ListBinCard::route('/'),
        ];
    }
}
