<?php

namespace App\Filament\Widgets;

use App\Models\Catalog\Product;
use App\Services\CurrentContext;
use App\Support\Quantity;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Table;
use Filament\Widgets\TableWidget;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Auth;

/**
 * The low-stock list from IsmsDashboardController::index(): products at or
 * below 5 units in the selected branch, lowest first, capped at 30 — the same
 * threshold, ordering and cap as the source.
 *
 * `stock` is a `withSum()` subquery alias, not a real aggregate column, and a
 * `HAVING "stock" <= 5` referencing it is rejected outright by SQLite ("HAVING
 * clause on a non-aggregate query") even though MySQL accepts it — so, exactly
 * as the source controller does, the threshold is applied in PHP on the loaded
 * collection rather than pushed into SQL.
 */
class LowStockWidget extends TableWidget
{
    protected static ?int $sort = 2;

    protected int|string|array $columnSpan = 'full';

    /** The source's hardcoded low-stock threshold. */
    public const THRESHOLD = 5;

    public static function canView(): bool
    {
        return Auth::user()?->hasPermissionTo('dashboard.access') ?? false;
    }

    public function table(Table $table): Table
    {
        $branchId = app(CurrentContext::class)->branchId();

        $lowStockIds = Product::query()
            ->withStockFor($branchId)
            ->get(['id', 'stock'])
            ->filter(fn (Product $p): bool => ((float) ($p->stock ?? 0)) <= self::THRESHOLD)
            ->sortBy('stock')
            ->take(30)
            ->pluck('id');

        return $table
            ->heading('Low stock')
            ->description('At or below '.self::THRESHOLD.' units.')
            ->query(
                fn (): Builder => Product::query()
                    ->with('baseUnit:id,code,name,is_fractional')
                    ->withStockFor($branchId)
                    ->whereIn('id', $lowStockIds)
            )
            ->defaultSort('stock', 'asc')
            ->paginated(false)
            ->columns([
                TextColumn::make('name')->label('Product')->searchable(),
                TextColumn::make('sku')->label('SKU')->placeholder('—'),
                TextColumn::make('stock')
                    ->label('Quantity')
                    ->formatStateUsing(fn ($state, Product $record): string => Quantity::format($state, $record->baseUnit))
                    ->color(fn ($state): string => ((float) $state) <= 0 ? 'danger' : 'warning'),
            ]);
    }
}
