<?php

declare(strict_types=1);

namespace App\Filament\Resources\DberpPurchaseExceptions;

use App\Business\Purchase\Enums\PurchaseExceptionResolutionResult;
use App\Business\Purchase\Enums\PurchaseExceptionStatus;
use App\Business\Purchase\Enums\PurchaseExceptionType;
use App\Business\Purchase\PurchaseExceptionService;
use App\Filament\Concerns\InteractsWithDberpPermissions;
use App\Filament\Resources\DberpPurchaseExceptions\Pages\EditDberpPurchaseException;
use App\Filament\Resources\DberpPurchaseExceptions\Pages\ListDberpPurchaseExceptions;
use App\Models\DberpPurchaseException;
use App\Services\DberpPermissionService;
use App\Support\DberpNumberFormatter;
use App\Support\DberpProductSkuSelectOptions;
use BackedEnum;
use Filament\Actions\EditAction;
use Filament\Forms\Components\DateTimePicker;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\Textarea;
use Filament\Forms\Components\TextInput;
use Filament\Resources\Resource;
use Filament\Schemas\Components\Section;
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 DberpPurchaseExceptionResource extends Resource
{
    use InteractsWithDberpPermissions;

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

    protected static ?string $recordTitleAttribute = 'code';

    protected static ?int $navigationSort = 50;

    public static function form(Schema $schema): Schema
    {
        return $schema->components([
            Section::make(__('dberp.resources.purchase_exception.label'))
                ->schema([
                    TextInput::make('code')->label(__('dberp.fields.document_code'))->disabled(),
                    TextInput::make('purchase_order_code')->label(__('dberp.fields.purchase_order_code'))->disabled(),
                    TextInput::make('purchase_receipt_code')->label(__('dberp.fields.purchase_receipt_code'))->disabled(),
                    Select::make('supplier_id')->label(__('dberp.fields.supplier'))->relationship('supplier', 'name')->disabled()->dehydrated(false),
                    DberpProductSkuSelectOptions::configureInventoryProductRelationshipSelect(
                        Select::make('product_id')->label(__('dberp.fields.product')),
                    )->disabled()->dehydrated(false),
                    Select::make('exception_type')->label(__('dberp.fields.exception_type'))->options(PurchaseExceptionType::options())->disabled(),
                    Select::make('status')->label(__('dberp.fields.exception_status'))->options(PurchaseExceptionStatus::options())->disabled(),
                    TextInput::make('arrival_quantity')->label(__('dberp.fields.arrival_quantity'))->disabled(),
                    TextInput::make('received_quantity')->label(__('dberp.fields.receipt_quantity'))->disabled(),
                    TextInput::make('rejected_quantity')->label(__('dberp.fields.rejected_quantity'))->disabled(),
                    TextInput::make('difference_quantity')->label(__('dberp.fields.difference_quantity'))->disabled(),
                    TextInput::make('pending_quantity')->label(__('dberp.fields.pending_quantity'))->disabled(),
                    Textarea::make('reason_detail')->label(__('dberp.fields.reason_detail'))->rows(3)->columnSpanFull(),
                    Textarea::make('handling_suggestion')->label(__('dberp.fields.handling_suggestion'))->rows(3)->columnSpanFull(),
                    Select::make('resolution_result')->label(__('dberp.fields.resolution_result'))->options(PurchaseExceptionResolutionResult::options()),
                    Textarea::make('resolution_remark')->label(__('dberp.fields.resolution_remark'))->rows(3)->columnSpanFull(),
                    DateTimePicker::make('occurred_at')->label(__('dberp.fields.occurred_at'))->disabled(),
                    DateTimePicker::make('handled_at')->label(__('dberp.fields.handled_at'))->disabled(),
                    DateTimePicker::make('closed_at')->label(__('dberp.fields.closed_at'))->disabled(),
                ])
                ->columns(3),
        ])->columns(1);
    }

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

    public static function table(Table $table): Table
    {
        return $table
            ->defaultSort('occurred_at', 'desc')
            ->columns([
                TextColumn::make('code')->label(__('dberp.fields.document_code'))->searchable(),
                TextColumn::make('purchase_order_code')->label(__('dberp.fields.purchase_order_code'))->searchable(),
                TextColumn::make('purchase_receipt_code')->label(__('dberp.fields.purchase_receipt_code'))->searchable(),
                TextColumn::make('supplier.name')->label(__('dberp.fields.supplier'))->searchable(),
                TextColumn::make('product.name')->label(__('dberp.fields.product_name'))->searchable(),
                TextColumn::make('exception_type')->label(__('dberp.fields.exception_type'))->badge()->formatStateUsing(fn (?string $state): string => PurchaseExceptionType::options()[$state] ?? (string) $state),
                TextColumn::make('status')->label(__('dberp.fields.exception_status'))->badge()->formatStateUsing(fn (?string $state): string => PurchaseExceptionStatus::options()[$state] ?? (string) $state),
                TextColumn::make('resolution_result')->label(__('dberp.fields.resolution_result'))->badge()->formatStateUsing(fn (?string $state): string => PurchaseExceptionResolutionResult::options()[$state] ?? (string) $state),
                TextColumn::make('difference_quantity')->label(__('dberp.fields.difference_quantity'))->formatStateUsing(fn ($state): string => DberpNumberFormatter::quantity($state)),
                TextColumn::make('pending_quantity')->label(__('dberp.fields.pending_quantity'))->formatStateUsing(fn ($state): string => DberpNumberFormatter::quantity($state)),
                TextColumn::make('occurred_at')->label(__('dberp.fields.occurred_at'))->dateTime(),
            ])
            ->filters([
                SelectFilter::make('supplier_id')->label(__('dberp.fields.supplier'))->relationship('supplier', 'name'),
                SelectFilter::make('exception_type')->label(__('dberp.fields.exception_type'))->options(PurchaseExceptionType::options()),
                SelectFilter::make('status')->label(__('dberp.fields.exception_status'))->options(PurchaseExceptionStatus::options()),
                SelectFilter::make('resolution_result')->label(__('dberp.fields.resolution_result'))->options(PurchaseExceptionResolutionResult::options()),
                Filter::make('is_pending')->label(__('dberp.fields.is_pending'))->query(fn (Builder $query): Builder => $query->whereIn('status', [PurchaseExceptionStatus::Pending->value, PurchaseExceptionStatus::Processing->value])),
            ])
            ->recordActions([
                EditAction::make(),
            ]);
    }

    public static function getPages(): array
    {
        return [
            'index' => ListDberpPurchaseExceptions::route('/'),
            'edit' => EditDberpPurchaseException::route('/{record}/edit'),
        ];
    }

    public static function canViewAny(): bool
    {
        return static::allowsAnyPermission([
            DberpPermissionService::VIEW_PURCHASE_EXCEPTION,
            DberpPermissionService::HANDLE_PURCHASE_EXCEPTION,
        ]);
    }

    public static function canCreate(): bool
    {
        return false;
    }

    public static function canEdit(Model $record): bool
    {
        return static::allowsPermission(DberpPermissionService::HANDLE_PURCHASE_EXCEPTION);
    }

    public static function canView(Model $record): bool
    {
        return static::canViewAny();
    }

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

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

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

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