<?php

declare(strict_types=1);

namespace App\Filament\Resources\DberpInventoryTransactions;

use App\Business\Inventory\Enums\InventoryBusinessType;
use App\Business\Inventory\Enums\InventoryChangeDirection;
use App\Filament\Concerns\InteractsWithDberpPermissions;
use App\Filament\Resources\Concerns\HasDberpExportAction;
use App\Filament\Resources\DberpInventoryTransactions\Pages\ListDberpInventoryTransactions;
use App\Models\DberpInventoryTransaction;
use App\Models\DberpProductSku;
use App\Services\DberpPermissionService;
use App\Support\DberpInventoryTransactionPresentation;
use App\Support\DberpNumberFormatter;
use App\Support\DberpProductSkuSelectOptions;
use BackedEnum;
use Filament\Forms\Components\DatePicker;
use Filament\Resources\Resource;
use Filament\Schemas\Schema;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Filters\Filter;
use Filament\Tables\Filters\SelectFilter;
use Filament\Tables\Table;
use Illuminate\Contracts\Support\Htmlable;
use Illuminate\Database\Eloquent\Builder;
use UnitEnum;

class DberpInventoryTransactionResource extends Resource
{
    use HasDberpExportAction;
    use InteractsWithDberpPermissions;

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

    protected static ?string $recordTitleAttribute = 'business_number';

    protected static ?int $navigationSort = 20;

    public static function getEloquentQuery(): Builder
    {
        return parent::getEloquentQuery()->with(['postingBaseUnit', 'postingAuxiliaryUnit', 'documentInputUnit']);
    }

    public static function form(Schema $schema): Schema
    {
        return $schema;
    }

    public static function table(Table $table): Table
    {
        return $table
            ->defaultSort('business_time', 'desc')
            ->columns([
                TextColumn::make('business_time')
                    ->label(__('dberp.fields.business_time'))
                    ->dateTime()
                    ->sortable(),
                TextColumn::make('business_type')
                    ->label(__('dberp.fields.business_type'))
                    ->badge()
                    ->formatStateUsing(fn (?string $state): string => InventoryBusinessType::tryFrom((string) $state)?->label() ?? (string) $state),
                TextColumn::make('direction')
                    ->label(__('dberp.fields.direction'))
                    ->badge()
                    ->formatStateUsing(fn (?string $state): string => InventoryChangeDirection::tryFrom((string) $state)?->label() ?? (string) $state),
                TextColumn::make('product.name')
                    ->label(__('dberp.fields.product_name'))
                    ->formatStateUsing(function ($state, DberpInventoryTransaction $record): string {
                        if ($record->product_name !== null && $record->product_name !== '') {
                            return (string) $record->product_name;
                        }

                        return (string) ($record->product?->name ?? '');
                    })
                    ->searchable(),
                TextColumn::make('product_code')
                    ->label(__('dberp.fields.product_code'))
                    ->placeholder('—')
                    ->toggleable(isToggledHiddenByDefault: true),
                TextColumn::make('sku_code')
                    ->label(__('dberp.fields.spec_combo_code'))
                    ->toggleable(),
                TextColumn::make('spec_text')
                    ->label(__('dberp.fields.spec_combo_summary'))
                    ->limit(40)
                    ->toggleable(),
                TextColumn::make('unit_name')
                    ->label(__('dberp.fields.product_base_unit'))
                    ->toggleable(isToggledHiddenByDefault: true),
                TextColumn::make('document_entered_display')
                    ->label(__('dberp.fields.inventory_ledger_entered_quantity'))
                    ->state(fn (DberpInventoryTransaction $record): string => DberpInventoryTransactionPresentation::documentEnteredDisplay($record))
                    ->toggleable(),
                TextColumn::make('posting_conversion_snapshot')
                    ->label(__('dberp.fields.inventory_ledger_posting_conversion_snapshot'))
                    ->state(fn (DberpInventoryTransaction $record): string => DberpInventoryTransactionPresentation::postingConversionSnapshotDisplay($record))
                    ->wrap()
                    ->toggleable(isToggledHiddenByDefault: true),
                TextColumn::make('warehouse.name')
                    ->label(__('dberp.fields.warehouse'))
                    ->searchable(),
                TextColumn::make('change_quantity')
                    ->label(__('dberp.fields.inventory_ledger_primary_base_change'))
                    ->formatStateUsing(fn ($state, DberpInventoryTransaction $record): string => DberpInventoryTransactionPresentation::primaryBaseChangeDisplay($record)),
                TextColumn::make('before_quantity')
                    ->label(__('dberp.fields.before_quantity'))
                    ->formatStateUsing(fn ($state): string => DberpNumberFormatter::quantity($state)),
                TextColumn::make('after_quantity')
                    ->label(__('dberp.fields.after_quantity'))
                    ->formatStateUsing(fn ($state): string => DberpNumberFormatter::quantity($state)),
                TextColumn::make('business_number')
                    ->label(__('dberp.fields.business_number'))
                    ->searchable(),
                TextColumn::make('operator.name')
                    ->label(__('dberp.fields.operator')),
            ])
            ->filters([
                SelectFilter::make('direction')
                    ->label(__('dberp.fields.direction'))
                    ->options(__('dberp.options.inventory_direction')),
                SelectFilter::make('business_type')
                    ->label(__('dberp.fields.business_type'))
                    ->options(__('dberp.options.inventory_business_type')),
                SelectFilter::make('warehouse_id')
                    ->label(__('dberp.fields.warehouse'))
                    ->relationship('warehouse', 'name'),
                DberpProductSkuSelectOptions::configureProductRelationshipTableFilter(
                    SelectFilter::make('product_id')
                        ->label(__('dberp.fields.product')),
                ),
                SelectFilter::make('product_sku_id')
                    ->label(__('dberp.fields.product_spec'))
                    ->relationship(
                        name: 'productSku',
                        titleAttribute: 'sku_code',
                        modifyQueryUsing: fn (Builder $query): Builder => $query->with(['product.unit'])->orderBy('product_id')->orderBy('id'),
                    )
                    ->getOptionLabelFromRecordUsing(fn (DberpProductSku $record): string => DberpProductSkuSelectOptions::labelForSku($record))
                    ->searchable(),
                Filter::make('business_time')
                    ->schema([
                        DatePicker::make('from')->label(__('dberp.fields.date_from')),
                        DatePicker::make('until')->label(__('dberp.fields.date_until')),
                    ])
                    ->query(function (Builder $query, array $data): Builder {
                        return $query
                            ->when($data['from'] ?? null, fn (Builder $builder, $date): Builder => $builder->whereDate('business_time', '>=', $date))
                            ->when($data['until'] ?? null, fn (Builder $builder, $date): Builder => $builder->whereDate('business_time', '<=', $date));
                    }),
            ])
            ->headerActions([
                static::makeExportAction('inventory-transaction-query'),
            ]);
    }

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

    public static function canViewAny(): bool
    {
        return static::allowsPermission(DberpPermissionService::NAV_INVENTORY_TRANSACTION_QUERY);
    }

    public static function getNavigationGroup(): string|UnitEnum|null
    {
        return __('dberp.nav.warehouse');
    }

    public static function getNavigationIcon(): string|BackedEnum|Htmlable|null
    {
        return null;
    }

    public static function getModelLabel(): string
    {
        return __('dberp.resources.inventory_transaction.label');
    }

    public static function getPluralModelLabel(): string
    {
        return __('dberp.resources.inventory_transaction.plural');
    }
}
