<?php

declare(strict_types=1);

namespace App\Filament\Resources\DberpProductOperationQueries;

use App\Business\Report\QueryCenterService;
use App\Filament\Concerns\InteractsWithDberpPermissions;
use App\Filament\Resources\Concerns\HasDberpExportAction;
use App\Filament\Resources\DberpProductOperationQueries\Pages\ListDberpProductOperationQueries;
use App\Models\DberpProduct;
use App\Models\DberpProductSku;
use App\Services\DberpPermissionService;
use App\Support\DberpFilamentMasterDataSelectOptions;
use App\Support\DberpNumberFormatter;
use App\Support\DberpProductOperationSourceUrlResolver;
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\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 DberpProductOperationQueryResource extends Resource
{
    use HasDberpExportAction;
    use InteractsWithDberpPermissions;

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

    protected static ?string $recordTitleAttribute = 'name';

    protected static ?int $navigationSort = 20;

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

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

    public static function table(Table $table): Table
    {
        return $table
            ->columns([
                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(query: function (Builder $query, string $search): Builder {
                        return $query->where(function (Builder $builder) use ($search): void {
                            $builder
                                ->where('code', 'like', '%'.$search.'%')
                                ->orWhereHas('product', fn (Builder $productQuery) => $productQuery->where('code', 'like', '%'.$search.'%'));
                        });
                    }),
                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(query: function (Builder $query, string $search): Builder {
                        return $query->where(function (Builder $builder) use ($search): void {
                            $builder
                                ->where('name', 'like', '%'.$search.'%')
                                ->orWhereHas('product', fn (Builder $productQuery) => $productQuery->where('name', 'like', '%'.$search.'%'));
                        });
                    }),
                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('current_stock_quantity')->label(__('dberp.fields.current_stock_quantity'))->tooltip(__('dberp.hints.report_quantity_in_base_unit'))->formatStateUsing(fn ($state): string => DberpNumberFormatter::quantity($state)),
                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)),
                TextColumn::make('purchase_quantity')->label(__('dberp.fields.purchase_quantity'))->tooltip(__('dberp.hints.report_quantity_in_base_unit'))->formatStateUsing(fn ($state): string => DberpNumberFormatter::quantity($state)),
                TextColumn::make('purchase_amount')->label(__('dberp.fields.purchase_amount'))->formatStateUsing(fn ($state): string => DberpNumberFormatter::money($state)),
            ])
            ->filters([
                SelectFilter::make('business_aggregate_level')
                    ->label(__('dberp.fields.business_query_aggregate_level'))
                    ->options(__('dberp.options.business_aggregate_level'))
                    ->default('product')
                    ->query(fn (Builder $query): Builder => $query),
                SelectFilter::make('customer_id')->label(__('dberp.fields.customer'))->options(fn (): array => DberpFilamentMasterDataSelectOptions::customers())->query(function (Builder $query, array $data): Builder {
                    if (! ($data['value'] ?? null)) {
                        return $query;
                    }

                    return QueryCenterService::applyProductOperationCustomerListingFilter($query, (int) $data['value']);
                }),
                SelectFilter::make('supplier_id')->label(__('dberp.fields.supplier'))->options(fn (): array => DberpFilamentMasterDataSelectOptions::suppliers())->query(function (Builder $query, array $data): Builder {
                    if (! ($data['value'] ?? null)) {
                        return $query;
                    }

                    return QueryCenterService::applyProductOperationSupplierListingFilter($query, (int) $data['value']);
                }),
                SelectFilter::make('warehouse_id')
                    ->label(__('dberp.fields.warehouse'))
                    ->options(fn (): array => DberpFilamentMasterDataSelectOptions::warehouses(enabledOnly: false))
                    ->query(fn (Builder $query): Builder => $query),
                SelectFilter::make('category_id')->label(__('dberp.fields.category'))->options(fn (): array => DberpFilamentMasterDataSelectOptions::productCategories())->query(function (Builder $query, array $data): Builder {
                    if (! ($data['value'] ?? null)) {
                        return $query;
                    }

                    $categoryId = (int) $data['value'];
                    if ($query->getModel() instanceof DberpProductSku) {
                        return $query->whereHas('product', fn (Builder $productQuery) => $productQuery->where('category_id', $categoryId));
                    }

                    return $query->where('category_id', $categoryId);
                }),
                SelectFilter::make('product_id')->label(__('dberp.fields.product'))->options(fn (): array => DberpFilamentMasterDataSelectOptions::products())->query(function (Builder $query, array $data): Builder {
                    if (! ($data['value'] ?? null)) {
                        return $query;
                    }

                    return QueryCenterService::applyProductOperationProductIdListingFilter($query, (int) $data['value']);
                }),
                DberpProductSkuSelectOptions::configureProductSkuTableFilter(
                    SelectFilter::make('product_sku_id')
                        ->label(__('dberp.fields.product_spec')),
                )->query(function (Builder $query, array $data): Builder {
                    if (! ($data['value'] ?? null)) {
                        return $query;
                    }

                    return QueryCenterService::applyProductOperationProductSkuIdListingFilter($query, (int) $data['value']);
                }),
                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 QueryCenterService::applyProductOperationBusinessTimeListingFilter($query, $data);
                    }),
            ])
            ->headerActions([
                static::makeExportAction('product-business-query'),
            ])
            ->recordActions([
                Action::make('view_product')
                    ->label(__('dberp.actions.view_product'))
                    ->url(fn (Model $record): ?string => DberpProductOperationSourceUrlResolver::productViewUrl($record))
                    ->visible(fn (Model $record): bool => DberpProductOperationSourceUrlResolver::productViewUrl($record) !== null),
                Action::make('view_inventory')
                    ->label(__('dberp.actions.view_inventory_balance'))
                    ->url(function (Model $record, ListDberpProductOperationQueries $livewire): ?string {
                        return DberpProductOperationSourceUrlResolver::inventoryBalanceIndexUrl(
                            $record,
                            is_array($livewire->tableFilters ?? null) ? $livewire->tableFilters : [],
                        );
                    })
                    ->visible(fn (Model $record): bool => DberpProductOperationSourceUrlResolver::productViewUrl($record) !== null),
            ])
            ->defaultSort('sales_amount', 'desc');
    }

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

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

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

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

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

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