<?php

declare(strict_types=1);

namespace App\Filament\Resources\DberpPurchaseInquiries\Concerns;

use App\Filament\Resources\DberpPurchaseInquiries\DberpPurchaseInquiryResource;
use App\Filament\Support\DberpFilamentNumberFields;
use App\Models\DberpEmployee;
use App\Models\DberpPurchaseRequest;
use App\Models\DberpPurchaseRequestItem;
use App\Models\DberpSupplier;
use App\Support\DberpDocumentLineSpecPresentation;
use App\Support\DberpNumberFormatter;
use Filament\Forms\Components\Component;
use Filament\Forms\Components\DatePicker;
use Filament\Forms\Components\Hidden;
use Filament\Forms\Components\Repeater;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\Textarea;
use Filament\Forms\Components\TextInput;
use Filament\Schemas\Components\Section;
use Filament\Schemas\Components\Utilities\Get;
use Filament\Schemas\Components\Utilities\Set;
use Illuminate\Database\Eloquent\Builder;

trait ProvidesDberpPurchaseInquiryFromRequestFormFields
{
    /**
     * @return list<Component|\Filament\Schemas\Components\Component>
     */
    protected function purchaseInquiryFromRequestFormSections(): array
    {
        return [
            Section::make(__('dberp.sections.purchase_inquiry_from_request'))
                ->schema([
                    Select::make('purchase_request_id')
                        ->label(__('dberp.fields.purchase_request'))
                        ->options(fn (): array => DberpPurchaseInquiryResource::selectablePurchaseRequestOptions())
                        ->searchable()
                        ->preload()
                        ->live()
                        ->afterStateUpdated(function (Set $set, Get $get, ?int $state): void {
                            $set('lines', $this->buildInquiryLinesFromPurchaseRequest($state));
                            if ($state) {
                                $request = DberpPurchaseRequest::query()->find($state);
                                $set('handler_employee_id', $request?->applicant_employee_id);
                                $set('supplier_ids', $request?->suggested_supplier_id ? [(int) $request->suggested_supplier_id] : []);
                            }
                        })
                        ->required(),
                    DatePicker::make('inquiry_date')
                        ->label(__('dberp.fields.purchase_inquiry_date'))
                        ->default(fn () => now()->toDateString())
                        ->required(),
                    Select::make('handler_employee_id')
                        ->label(__('dberp.fields.handler_employee'))
                        ->options(fn (): array => DberpEmployee::selectOptionsForFilament(fn (Builder $q) => $q->where('is_enabled', true)))
                        ->searchable()
                        ->preload(),
                    Select::make('supplier_ids')
                        ->label(__('dberp.fields.inquiry_suppliers'))
                        ->options(fn (): array => DberpSupplier::query()->where('is_enabled', true)->orderBy('sort_order')->orderBy('id')->pluck('name', 'id')->all())
                        ->multiple()
                        ->searchable()
                        ->preload()
                        ->required(),
                    Textarea::make('remark')
                        ->label(__('dberp.fields.remark'))
                        ->rows(2)
                        ->columnSpanFull(),
                    Repeater::make('lines')
                        ->label(__('dberp.sections.purchase_request_line_selection'))
                        ->columnSpanFull()
                        ->addable(false)
                        ->deletable(false)
                        ->reorderable(false)
                        ->schema([
                            Hidden::make('purchase_request_item_id'),
                            TextInput::make('product_label')
                                ->label(__('dberp.fields.product'))
                                ->disabled()
                                ->dehydrated(false),
                            TextInput::make('remaining_quantity')
                                ->label(__('dberp.fields.remaining_quantity'))
                                ->disabled()
                                ->dehydrated(false)
                                ->formatStateUsing(fn ($state): string => DberpNumberFormatter::quantity($state)),
                            DberpFilamentNumberFields::documentLineQuantityInput(
                                TextInput::make('inquiry_quantity')
                                    ->label(__('dberp.fields.inquiry_quantity'))
                                    ->required(),
                            ),
                        ])
                        ->columns(3),
                ])
                ->columns(2),
        ];
    }

    /**
     * @return list<array<string, mixed>>
     */
    protected function buildInquiryLinesFromPurchaseRequest(?int $purchaseRequestId): array
    {
        if ($purchaseRequestId === null || $purchaseRequestId <= 0) {
            return [];
        }

        $request = DberpPurchaseRequest::query()
            ->with(['items.product', 'items.productSku'])
            ->find($purchaseRequestId);

        if ($request === null) {
            return [];
        }

        return $request->items
            ->filter(fn (DberpPurchaseRequestItem $item): bool => (float) $item->remaining_quantity > 0.00005)
            ->map(fn (DberpPurchaseRequestItem $item): array => [
                'purchase_request_item_id' => $item->getKey(),
                'product_label' => $this->formatPurchaseRequestItemLabel($item),
                'remaining_quantity' => $item->remaining_quantity,
                'inquiry_quantity' => $item->remaining_quantity,
            ])
            ->values()
            ->all();
    }

    /**
     * @param  array<string, mixed>  $data
     * @return array<int, float>
     */
    protected function extractInquiryLineQuantitiesFromForm(array $data): array
    {
        $quantities = [];

        foreach ((array) ($data['lines'] ?? []) as $line) {
            if (! is_array($line)) {
                continue;
            }

            $itemId = (int) ($line['purchase_request_item_id'] ?? 0);
            $quantity = (float) ($line['inquiry_quantity'] ?? 0);

            if ($itemId <= 0 || $quantity <= 0) {
                continue;
            }

            $quantities[$itemId] = $quantity;
        }

        return $quantities;
    }

    protected function formatPurchaseRequestItemLabel(DberpPurchaseRequestItem $item): string
    {
        $item->loadMissing(DberpDocumentLineSpecPresentation::eagerLoadsForDocumentLines(['product', 'productSku']));

        $name = $item->product?->name ?? (string) __('dberp.fields.product').' #'.$item->product_id;
        $spec = DberpDocumentLineSpecPresentation::lineSpecSummary($item);

        return $spec !== '' ? $name.' · '.$spec : $name;
    }
}
