<?php

declare(strict_types=1);

/**
 * 本文件属于 DBErp 进销存系统。
 *
 * 版权所有 © 2026 北京珑大钜商科技有限公司。保留所有权利。
 *
 * 未经官方授权，不得删除、篡改或隐藏本文件中的版权声明、产品标识与来源信息。
 * 商业授权、官方更新与技术支持服务，请以珑大官方支持中心记录为准。
 *
 * @link https://support.loongdom.cn
 * @see  https://www.dberp.com.cn
 */

namespace App\Filament\Resources\DberpInventorySummaries;

use App\Business\Report\InventoryReportService;
use App\Filament\Concerns\InteractsWithDberpPermissions;
use App\Filament\Resources\Concerns\HasDberpExportAction;
use App\Filament\Resources\DberpInventorySummaries\Pages\ListDberpInventorySummaries;
use App\Models\DberpInventoryBalance;
use App\Models\DberpProductCategory;
use App\Models\DberpProductSku;
use App\Services\DberpPermissionService;
use App\Support\DberpFilamentMasterDataSelectOptions;
use App\Support\DberpInventorySummaryFilamentSupport;
use App\Support\DberpNumberFormatter;
use App\Support\DberpProductSkuSelectOptions;
use App\Support\DberpReportSkuPresentation;
use BackedEnum;
use Filament\Actions\Action;
use Filament\Forms\Components\DatePicker;
use Filament\Resources\Resource;
use Filament\Schemas\Schema;
use Filament\Tables\Columns\Summarizers\Sum;
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 DberpInventorySummaryResource extends Resource
{
    use HasDberpExportAction;
    use InteractsWithDberpPermissions;

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

    protected static ?int $navigationSort = 20;

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

    public static function getEloquentQuery(): Builder
    {
        return app(InventoryReportService::class)->summaryQuery();
    }

    public static function table(Table $table): Table
    {
        return $table
            ->defaultSort('available_quantity', 'asc')
            ->columns([
                TextColumn::make('product.code')->label(__('dberp.fields.product_code'))->searchable(),
                TextColumn::make('product.name')->label(__('dberp.fields.product_name'))->searchable(),
                TextColumn::make('productSku.spec_text')
                    ->label(__('dberp.fields.spec_combo_summary'))
                    ->placeholder('—')
                    ->formatStateUsing(function ($state, DberpInventoryBalance $record): string {
                        return DberpReportSkuPresentation::inventoryBalanceSpecSummary(
                            $record->getAttribute('product_sku_id') !== null ? (int) $record->getAttribute('product_sku_id') : null,
                            (string) ($record->productSku?->spec_text ?? $state ?? ''),
                            (string) ($record->productSku?->sku_code ?? ''),
                        );
                    })
                    ->limit(48)
                    ->toggleable(isToggledHiddenByDefault: true),
                TextColumn::make('productSku.sku_code')
                    ->label(__('dberp.fields.spec_combo_code'))
                    ->placeholder('—')
                    ->formatStateUsing(function ($state, DberpInventoryBalance $record): string {
                        $skuId = $record->getAttribute('product_sku_id') !== null ? (int) $record->getAttribute('product_sku_id') : null;
                        if ($skuId === null || $skuId === 0) {
                            return DberpReportSkuPresentation::unspecifiedSpecLabel();
                        }

                        $code = trim((string) ($record->productSku?->sku_code ?? $state ?? ''));

                        return $code !== '' ? $code : DberpReportSkuPresentation::unspecifiedSpecLabel();
                    })
                    ->searchable()
                    ->toggleable(isToggledHiddenByDefault: true),
                TextColumn::make('product.category.name')
                    ->label(__('dberp.fields.category'))
                    ->toggleable(isToggledHiddenByDefault: true),
                TextColumn::make('warehouse.name')->label(__('dberp.fields.warehouse')),
                TextColumn::make('realtime_quantity')
                    ->label(__('dberp.fields.realtime_quantity'))
                    ->formatStateUsing(fn ($state): string => DberpNumberFormatter::quantity($state))
                    ->summarize(Sum::make()->label(__('dberp.fields.table_sum_label'))),
                TextColumn::make('available_quantity')
                    ->label(__('dberp.fields.available_quantity'))
                    ->formatStateUsing(fn ($state): string => DberpNumberFormatter::quantity($state))
                    ->summarize(Sum::make()->label(__('dberp.fields.table_sum_label'))),
                TextColumn::make('total_in_quantity')
                    ->label(__('dberp.fields.total_in_quantity'))
                    ->tooltip(__('dberp.hints.inventory_summary_total_in_quantity'))
                    ->formatStateUsing(fn ($state): string => DberpNumberFormatter::quantity($state))
                    ->summarize(Sum::make()->label(__('dberp.fields.table_sum_label')))
                    ->toggleable(isToggledHiddenByDefault: true),
                TextColumn::make('total_out_quantity')
                    ->label(__('dberp.fields.total_out_quantity'))
                    ->tooltip(__('dberp.hints.inventory_summary_total_out_quantity'))
                    ->formatStateUsing(fn ($state): string => DberpNumberFormatter::quantity($state))
                    ->summarize(Sum::make()->label(__('dberp.fields.table_sum_label')))
                    ->toggleable(isToggledHiddenByDefault: true),
                TextColumn::make('purchase_in_quantity')
                    ->label(__('dberp.fields.purchase_in_quantity'))
                    ->formatStateUsing(fn ($state): string => DberpNumberFormatter::quantity($state))
                    ->summarize(Sum::make()->label(__('dberp.fields.table_sum_label')))
                    ->toggleable(isToggledHiddenByDefault: true),
                TextColumn::make('sales_out_quantity')
                    ->label(__('dberp.fields.sales_out_quantity'))
                    ->formatStateUsing(fn ($state): string => DberpNumberFormatter::quantity($state))
                    ->summarize(Sum::make()->label(__('dberp.fields.table_sum_label')))
                    ->toggleable(isToggledHiddenByDefault: true),
                TextColumn::make('transfer_in_quantity')
                    ->label(__('dberp.fields.transfer_in_quantity'))
                    ->tooltip(__('dberp.hints.inventory_summary_transfer_in_quantity'))
                    ->formatStateUsing(fn ($state): string => DberpNumberFormatter::quantity($state))
                    ->summarize(Sum::make()->label(__('dberp.fields.table_sum_label')))
                    ->toggleable(isToggledHiddenByDefault: true),
                TextColumn::make('transfer_out_quantity')
                    ->label(__('dberp.fields.transfer_out_quantity'))
                    ->tooltip(__('dberp.hints.inventory_summary_transfer_out_quantity'))
                    ->formatStateUsing(fn ($state): string => DberpNumberFormatter::quantity($state))
                    ->summarize(Sum::make()->label(__('dberp.fields.table_sum_label')))
                    ->toggleable(isToggledHiddenByDefault: true),
                TextColumn::make('last_moved_at')
                    ->label(__('dberp.fields.last_moved_at'))
                    ->dateTime()
                    ->toggleable(isToggledHiddenByDefault: true),
            ])
            ->filters([
                SelectFilter::make('aggregate_level')
                    ->label(__('dberp.fields.inventory_aggregate_level'))
                    ->options([
                        'sku_detail' => __('dberp.options.inventory_aggregate_level.sku_detail'),
                        'product_summary' => __('dberp.options.inventory_aggregate_level.product_summary'),
                    ])
                    ->default('sku_detail')
                    ->query(fn (Builder $query): Builder => $query),
                SelectFilter::make('warehouse_id')->label(__('dberp.fields.warehouse'))->relationship('warehouse', 'name'),
                DberpFilamentMasterDataSelectOptions::applyDeferredSearchForFilter(
                    SelectFilter::make('product_id')->label(__('dberp.fields.product')),
                    fn (): array => DberpFilamentMasterDataSelectOptions::products(),
                ),
                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(),
                SelectFilter::make('category_id')->label(__('dberp.fields.category'))->options(fn (): array => DberpProductCategory::query()->orderBy('sort_order')->orderBy('id')->pluck('name', 'id')->all())->query(fn (Builder $query, array $data): Builder => ($data['value'] ?? null) ? $query->whereHas('product', fn (Builder $productQuery) => $productQuery->where('category_id', (int) $data['value'])) : $query),
                Filter::make('business_time')
                    ->label(__('dberp.fields.business_time'))
                    ->schema([
                        DatePicker::make('from')->label(__('dberp.fields.date_from')),
                        DatePicker::make('until')->label(__('dberp.fields.date_until')),
                    ])
                    ->query(fn (Builder $query): Builder => $query),
            ])
            ->headerActions([
                static::makeExportAction('inventory-summary'),
            ])
            ->recordActions([
                Action::make('view_inventory_transactions')
                    ->label(__('dberp.actions.view_inventory_transactions'))
                    ->url(fn (DberpInventoryBalance $record, ListDberpInventorySummaries $livewire): string => DberpInventorySummaryFilamentSupport::inventoryTransactionIndexUrl(
                        $record,
                        is_array($livewire->tableFilters ?? null) ? $livewire->tableFilters : [],
                    ))
                    ->visible(fn (): bool => static::allowsPermission(DberpPermissionService::NAV_INVENTORY_TRANSACTION_QUERY)),
                Action::make('view_inventory_balance')
                    ->label(__('dberp.actions.view_inventory_balance'))
                    ->url(fn (DberpInventoryBalance $record, ListDberpInventorySummaries $livewire): string => DberpInventorySummaryFilamentSupport::inventoryBalanceIndexUrl(
                        $record,
                        is_array($livewire->tableFilters ?? null) ? $livewire->tableFilters : [],
                    ))
                    ->visible(fn (): bool => static::allowsPermission(DberpPermissionService::VIEW_INVENTORY_BALANCE)),
            ]);
    }

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

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

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

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

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

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