<?php

declare(strict_types=1);

namespace App\Filament\Resources\DberpProductSalesRankings;

use App\Business\Report\SalesReportService;
use App\Filament\Concerns\InteractsWithDberpPermissions;
use App\Filament\Resources\Concerns\HasDberpExportAction;
use App\Filament\Resources\DberpProducts\DberpProductResource;
use App\Filament\Resources\DberpProductSalesRankings\Pages\ListDberpProductSalesRankings;
use App\Filament\Resources\DberpSalesOrders\DberpSalesOrderResource;
use App\Models\DberpCustomer;
use App\Models\DberpEmployee;
use App\Models\DberpProduct;
use App\Models\DberpProductCategory;
use App\Models\DberpProductSku;
use App\Services\DberpPermissionService;
use App\Support\DberpFilamentMasterDataSelectOptions;
use App\Support\DberpNumberFormatter;
use App\Support\DberpProductSkuSelectOptions;
use App\Support\DberpReportSkuPresentation;
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 Illuminate\Database\Eloquent\Model;
use UnitEnum;

class DberpProductSalesRankingResource extends Resource
{
    use HasDberpExportAction;
    use InteractsWithDberpPermissions;

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

    protected static ?string $recordTitleAttribute = 'name';

    protected static ?int $navigationSort = 100;

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

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

        /** @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 (ListDberpProductSalesRankings $livewire, Model $record): int => $livewire->computeProductSalesRankingRank($record)),
                TextColumn::make('display_product_code')
                    ->label(__('dberp.fields.product_code'))
                    ->state(fn (Model $record): string => $record instanceof DberpProductSku
                        ? (string) ($record->product?->code ?? '')
                        : (string) $record->getAttribute('code'))
                    ->searchable(),
                TextColumn::make('display_product_name')
                    ->label(__('dberp.fields.product_name'))
                    ->state(fn (Model $record): string => $record instanceof DberpProductSku
                        ? (string) ($record->product?->name ?? '')
                        : (string) $record->getAttribute('name'))
                    ->searchable()
                    ->url(function (Model $record): ?string {
                        $product = $record instanceof DberpProductSku ? $record->product : $record;
                        if (! $product instanceof DberpProduct) {
                            return null;
                        }

                        return DberpProductResource::canEdit($product)
                            ? DberpProductResource::getUrl('edit', ['record' => $product])
                            : null;
                    }),
                TextColumn::make('display_category')
                    ->label(__('dberp.fields.category'))
                    ->state(fn (Model $record): string => $record instanceof DberpProductSku
                        ? (string) ($record->product?->category?->name ?? '')
                        : (string) ($record->category?->name ?? '')),
                TextColumn::make('display_spec_summary')
                    ->label(__('dberp.fields.spec_combo_summary'))
                    ->placeholder('—')
                    ->state(fn (Model $record): string => $record instanceof DberpProductSku
                        ? DberpReportSkuPresentation::skuRecordSpecSummary($record)
                        : '—'),
                TextColumn::make('display_spec_code')
                    ->label(__('dberp.fields.spec_combo_code'))
                    ->placeholder('—')
                    ->state(fn (Model $record): string => $record instanceof DberpProductSku
                        ? (string) ($record->sku_code ?? '')
                        : '—'),
                TextColumn::make('sales_order_count')->label(__('dberp.fields.order_count'))->numeric(),
                TextColumn::make('sales_quantity')->label(__('dberp.fields.sales_quantity'))->tooltip(__('dberp.hints.report_quantity_in_base_unit'))->formatStateUsing(fn ($state): string => DberpNumberFormatter::quantity($state)),
                TextColumn::make('sales_amount')->label(__('dberp.fields.sales_amount'))->formatStateUsing(fn ($state): string => DberpNumberFormatter::money($state)),
            ])
            ->filters([
                SelectFilter::make('ranking_dimension')
                    ->label(__('dberp.fields.report_ranking_dimension'))
                    ->options(__('dberp.options.report_ranking_dimension'))
                    ->default('product')
                    ->query(fn (Builder $query): Builder => $query),
                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('product-sales-ranking'),
            ])
            ->recordActions([
                Action::make('view_product')
                    ->label(__('dberp.resources.product_sales_ranking.link_view_product'))
                    ->url(function (Model $record): string {
                        $product = $record instanceof DberpProductSku ? $record->product : $record;
                        if (! $product instanceof DberpProduct) {
                            return DberpProductResource::getUrl('index');
                        }

                        return DberpProductResource::getUrl('edit', ['record' => $product]);
                    })
                    ->visible(function (Model $record): bool {
                        $product = $record instanceof DberpProductSku ? $record->product : $record;

                        return $product instanceof DberpProduct && DberpProductResource::canEdit($product);
                    }),
                Action::make('view_sales_orders')
                    ->label(__('dberp.resources.product_sales_ranking.link_sales_orders'))
                    ->url(fn (Model $record, ListDberpProductSalesRankings $livewire): string => DberpSalesStatisticsFilamentSupport::salesOrderIndexUrlForProductRanking(
                        $record,
                        is_array($livewire->tableFilters) ? $livewire->tableFilters : [],
                    ))
                    ->visible(fn (): bool => DberpSalesOrderResource::canViewAny()),
            ])
            ->defaultSort('sales_amount', 'desc');
    }

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

    public static function canViewAny(): bool
    {
        return static::allowsPermission(DberpPermissionService::NAV_PRODUCT_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.product_sales_ranking.label');
    }

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