<?php

declare(strict_types=1);

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

namespace App\Filament\Resources\DberpSalesStatistics;

use App\Business\Report\SalesReportService;
use App\Business\Sales\Enums\SalesOrderStatus;
use App\Business\Settlement\Enums\ReceivableStatus;
use App\Filament\Concerns\InteractsWithDberpPermissions;
use App\Filament\Resources\Concerns\HasDberpExportAction;
use App\Filament\Resources\DberpSalesOrders\DberpSalesOrderResource;
use App\Filament\Resources\DberpSalesStatistics\Pages\ListDberpSalesStatistics;
use App\Models\DberpEmployee;
use App\Models\DberpSalesOrder;
use App\Services\DberpPermissionService;
use App\Support\DberpFilamentMasterDataSelectOptions;
use App\Support\DberpNumberFormatter;
use App\Support\DberpProductSkuSelectOptions;
use App\Support\DberpSalesStatisticsFilamentSupport;
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 DberpSalesStatisticResource extends Resource
{
    use HasDberpExportAction;
    use InteractsWithDberpPermissions;

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

    protected static ?string $recordTitleAttribute = 'code';

    protected static ?int $navigationSort = 30;

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

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

    public static function table(Table $table): Table
    {
        return $table
            ->defaultSort('business_time', 'desc')
            ->columns([
                TextColumn::make('code')->label(__('dberp.fields.sales_order_code'))->searchable(),
                TextColumn::make('customer.name')->label(__('dberp.fields.customer'))->searchable(),
                TextColumn::make('handlerEmployee.name')
                    ->label(__('dberp.fields.handler_employee'))
                    ->toggleable(isToggledHiddenByDefault: true),
                TextColumn::make('status')
                    ->label(__('dberp.fields.status'))
                    ->badge()
                    ->formatStateUsing(fn (?string $state): string => __('dberp.options.sales_order_status')[$state] ?? (string) $state),
                TextColumn::make('business_time')
                    ->label(__('dberp.fields.business_time'))
                    ->dateTime()
                    ->toggleable(isToggledHiddenByDefault: true),
                TextColumn::make('total_quantity')
                    ->label(__('dberp.fields.total_quantity'))
                    ->formatStateUsing(fn ($state): string => DberpNumberFormatter::quantity($state))
                    ->summarize(Sum::make()->label(__('dberp.fields.table_sum_label'))),
                TextColumn::make('final_amount')
                    ->label(__('dberp.fields.final_amount'))
                    ->formatStateUsing(fn ($state): string => DberpNumberFormatter::money($state))
                    ->summarize(Sum::make()->label(__('dberp.fields.table_sum_label'))),
                TextColumn::make('receivable_amount')
                    ->label(__('dberp.fields.receivable_amount'))
                    ->formatStateUsing(fn ($state): string => DberpNumberFormatter::money($state))
                    ->summarize(Sum::make()->label(__('dberp.fields.table_sum_label')))
                    ->toggleable(isToggledHiddenByDefault: true),
                TextColumn::make('received_amount')
                    ->label(__('dberp.fields.received_amount'))
                    ->formatStateUsing(fn ($state): string => DberpNumberFormatter::money($state))
                    ->summarize(Sum::make()->label(__('dberp.fields.table_sum_label')))
                    ->toggleable(isToggledHiddenByDefault: true),
                TextColumn::make('unreceived_amount')
                    ->label(__('dberp.fields.unreceived_amount'))
                    ->formatStateUsing(fn ($state): string => DberpNumberFormatter::money($state))
                    ->summarize(Sum::make()->label(__('dberp.fields.table_sum_label'))),
                TextColumn::make('receivable_status')
                    ->label(__('dberp.fields.receivable_status'))
                    ->badge()
                    ->formatStateUsing(fn (?string $state): string => ReceivableStatus::tryFrom((string) $state)?->label() ?? (string) $state),
            ])
            ->filters([
                DberpFilamentMasterDataSelectOptions::applyDeferredSearchForFilter(
                    SelectFilter::make('customer_id')->label(__('dberp.fields.customer')),
                    fn (): array => DberpFilamentMasterDataSelectOptions::customers(),
                ),
                SelectFilter::make('status')->label(__('dberp.fields.status'))->options(SalesOrderStatus::statisticsScopeOptions()),
                SelectFilter::make('handler_employee_id')->label(__('dberp.fields.handler_employee'))->options(fn (): array => DberpEmployee::selectOptionsForFilament()),
                DberpFilamentMasterDataSelectOptions::applyDeferredSearchForFilter(
                    SelectFilter::make('category_id')->label(__('dberp.fields.category')),
                    fn (): array => DberpFilamentMasterDataSelectOptions::productCategories(),
                )->query(fn (Builder $query, array $data): Builder => ($data['value'] ?? null) ? $query->whereHas('items.product', fn (Builder $productQuery) => $productQuery->where('category_id', (int) $data['value'])) : $query),
                DberpFilamentMasterDataSelectOptions::applyDeferredSearchForFilter(
                    SelectFilter::make('product_id')->label(__('dberp.fields.product')),
                    fn (): array => DberpFilamentMasterDataSelectOptions::products(),
                )->query(fn (Builder $query, array $data): Builder => ($data['value'] ?? null) ? $query->whereHas('items', fn (Builder $itemQuery) => $itemQuery->where('product_id', (int) $data['value'])) : $query),
                DberpProductSkuSelectOptions::configureProductSkuTableFilter(
                    SelectFilter::make('product_sku_id')
                        ->label(__('dberp.fields.product_spec')),
                )->query(fn (Builder $query, array $data): Builder => ($data['value'] ?? null) ? $query->whereHas('items', fn (Builder $itemQuery) => $itemQuery->where('product_sku_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(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('sales-statistics'),
            ])
            ->recordActions([
                Action::make('view_sales_order')
                    ->label(__('dberp.actions.view_source_document'))
                    ->url(fn (DberpSalesOrder $record): string => DberpSalesStatisticsFilamentSupport::salesOrderEditUrl($record))
                    ->visible(fn (DberpSalesOrder $record): bool => DberpSalesOrderResource::canEdit($record)),
                Action::make('view_customer_receivables')
                    ->label(__('dberp.resources.sales_statistics.link_customer_receivables'))
                    ->url(fn (DberpSalesOrder $record, ListDberpSalesStatistics $livewire): string => DberpSalesStatisticsFilamentSupport::customerReceivableIndexUrl(
                        $record,
                        is_array($livewire->tableFilters ?? null) ? $livewire->tableFilters : [],
                    ))
                    ->visible(fn (): bool => static::allowsPermission(DberpPermissionService::VIEW_CUSTOMER_RECEIVABLE)),
            ]);
    }

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

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

    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.sales_statistics.label');
    }

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