<?php

declare(strict_types=1);

namespace App\Filament\Resources\DberpCustomerSalesRankings;

use App\Business\Report\SalesReportService;
use App\Filament\Concerns\InteractsWithDberpPermissions;
use App\Filament\Resources\Concerns\HasDberpExportAction;
use App\Filament\Resources\DberpCustomers\DberpCustomerResource;
use App\Filament\Resources\DberpCustomerSalesRankings\Pages\ListDberpCustomerSalesRankings;
use App\Filament\Resources\DberpSalesOrders\DberpSalesOrderResource;
use App\Models\DberpCustomer;
use App\Models\DberpEmployee;
use App\Models\DberpProductCategory;
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\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 DberpCustomerSalesRankingResource extends Resource
{
    use HasDberpExportAction;
    use InteractsWithDberpPermissions;

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

    protected static ?string $recordTitleAttribute = 'name';

    protected static ?int $navigationSort = 90;

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

    public static function getEloquentQuery(): Builder
    {
        $query = app(SalesReportService::class)->customerRankingQuery();

        /** @var Builder $query */
        return $query;
    }

    public static function table(Table $table): Table
    {
        $filterQueryPassthrough = fn (Builder $query, array $data): Builder => $query;

        return $table
            ->columns([
                TextColumn::make('ranking_serial')
                    ->label(__('dberp.fields.ranking_position'))
                    ->numeric()
                    ->state(fn (ListDberpCustomerSalesRankings $livewire, DberpCustomer $record): int => $livewire->computeCustomerSalesRankingRank($record)),
                TextColumn::make('code')->label(__('dberp.fields.customer_code'))->searchable(),
                TextColumn::make('name')
                    ->label(__('dberp.fields.customer_name'))
                    ->searchable()
                    ->url(fn (DberpCustomer $record): ?string => DberpCustomerResource::canEdit($record)
                        ? DberpCustomerResource::getUrl('edit', ['record' => $record])
                        : null),
                TextColumn::make('salesperson.name')->label(__('dberp.fields.salesperson')),
                TextColumn::make('order_count')->label(__('dberp.fields.order_count'))->numeric(),
                TextColumn::make('sales_amount')->label(__('dberp.fields.sales_amount'))->formatStateUsing(fn ($state): string => DberpNumberFormatter::money($state)),
                TextColumn::make('received_amount_total')->label(__('dberp.fields.received_amount'))->formatStateUsing(fn ($state): string => DberpNumberFormatter::money($state)),
            ])
            ->filters([
                Filter::make('business_time')
                    ->schema([
                        DatePicker::make('from')->label(__('dberp.fields.date_from')),
                        DatePicker::make('until')->label(__('dberp.fields.date_until')),
                    ])
                    ->query($filterQueryPassthrough),
                SelectFilter::make('status')
                    ->label(__('dberp.fields.status'))
                    ->options(__('dberp.options.sales_order_status'))
                    ->query($filterQueryPassthrough),
                SelectFilter::make('handler_employee_id')
                    ->label(__('dberp.fields.handler_employee'))
                    ->options(fn (): array => DberpEmployee::selectOptionsForFilament())
                    ->searchable()
                    ->preload()
                    ->query($filterQueryPassthrough),
                SelectFilter::make('customer_id')
                    ->label(__('dberp.fields.customer'))
                    ->options(fn (): array => DberpCustomer::query()->orderBy('sort_order')->orderBy('id')->pluck('name', 'id')->all())
                    ->query($filterQueryPassthrough),
                SelectFilter::make('category_id')
                    ->label(__('dberp.fields.category'))
                    ->options(fn (): array => DberpProductCategory::query()->orderBy('sort_order')->orderBy('id')->pluck('name', 'id')->all())
                    ->query($filterQueryPassthrough),
                SelectFilter::make('product_id')
                    ->label(__('dberp.fields.product'))
                    ->options(fn (): array => DberpFilamentMasterDataSelectOptions::products())
                    ->query($filterQueryPassthrough),
                DberpProductSkuSelectOptions::configureProductSkuTableFilter(
                    SelectFilter::make('product_sku_id')
                        ->label(__('dberp.fields.product_spec')),
                )->query($filterQueryPassthrough),
            ])
            ->headerActions([
                static::makeExportAction('customer-sales-ranking'),
            ])
            ->recordActions([
                Action::make('view_customer')
                    ->label(__('dberp.resources.customer_sales_ranking.link_view_customer'))
                    ->url(fn (DberpCustomer $record): string => DberpCustomerResource::getUrl('edit', ['record' => $record]))
                    ->visible(fn (DberpCustomer $record): bool => DberpCustomerResource::canEdit($record)),
                Action::make('view_sales_orders')
                    ->label(__('dberp.resources.customer_sales_ranking.link_sales_orders'))
                    ->url(fn (DberpCustomer $record, ListDberpCustomerSalesRankings $livewire): string => DberpSalesStatisticsFilamentSupport::salesOrderIndexUrlForCustomerRanking(
                        $record,
                        is_array($livewire->tableFilters) ? $livewire->tableFilters : [],
                    ))
                    ->visible(fn (): bool => DberpSalesOrderResource::canViewAny()),
            ])
            ->defaultSort('sales_amount', 'desc');
    }

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

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

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

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