<?php

declare(strict_types=1);

namespace App\Filament\Resources\DberpPurchaseRequests\RelationManagers;

use App\Business\Purchase\Enums\PurchaseRequestSourceType;
use App\Business\Purchase\Enums\PurchaseRequestStatus;
use App\Filament\Support\DberpFilamentNumberFields;
use App\Models\DberpProduct;
use App\Models\DberpWarehouse;
use App\Support\DberpDocumentLineBulkProductAddHeaderActions;
use App\Support\DberpDocumentLinePresentation;
use App\Support\DberpDocumentLineSpecPresentation;
use App\Support\DberpDocumentLineUnitFormFields;
use App\Support\DberpLineProductSkuFormFields;
use App\Support\DberpNumberFormatter;
use App\Support\DberpProductSkuSelectOptions;
use App\Support\DberpSystemProfileBusinessDefaults;
use Filament\Actions\CreateAction;
use Filament\Actions\DeleteAction;
use Filament\Actions\EditAction;
use Filament\Forms\Components\Hidden;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\Textarea;
use Filament\Forms\Components\TextInput;
use Filament\Resources\RelationManagers\RelationManager;
use Filament\Schemas\Components\Utilities\Get;
use Filament\Schemas\Components\Utilities\Set;
use Filament\Schemas\Schema;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Model;

class ItemsRelationManager extends RelationManager
{
    protected static string $relationship = 'items';

    public static function getTitle(Model $ownerRecord, string $pageClass): string
    {
        return __('dberp.relations.purchase_request_items');
    }

    protected static function getModelLabel(): ?string
    {
        return __('dberp.fields.purchase_request_item');
    }

    protected static function getPluralModelLabel(): ?string
    {
        return __('dberp.relations.purchase_request_items');
    }

    public function form(Schema $schema): Schema
    {
        $locksLine = fn (): bool => ! in_array($this->getOwnerRecord()->status, [PurchaseRequestStatus::Draft->value, PurchaseRequestStatus::Pending->value], true);

        return $schema->components(array_merge([
            Hidden::make('source_type')
                ->default(fn (): string => DberpSystemProfileBusinessDefaults::defaultPurchaseRequestSourceType()),
            DberpDocumentLineUnitFormFields::wireProductDriver(
                DberpProductSkuSelectOptions::configurePurchasableProductSelect(
                    Select::make('product_id')
                        ->label(__('dberp.fields.product'))
                        ->required(),
                ),
                DberpDocumentLineUnitFormFields::resolveProductFromProductIdField('product_id'),
                function (Set $set, Get $get): void {
                    DberpLineProductSkuFormFields::syncAfterProductIdChanged($set, $get, 'product_id');
                },
            ),
        ], DberpLineProductSkuFormFields::specificationComboFields('product_id', $locksLine), DberpDocumentLineUnitFormFields::blocks(
            DberpDocumentLineUnitFormFields::resolveProductFromProductIdField('product_id'),
            false,
            $locksLine,
        ), DberpDocumentLineUnitFormFields::withApproxBasePreviewAfterQuantityField([
            TextInput::make('external_sku')
                ->label(__('dberp.fields.external_sku'))
                ->maxLength(128),
            Select::make('warehouse_id')
                ->label(__('dberp.fields.warehouse'))
                ->options(fn (): array => DberpWarehouse::query()
                    ->where('is_enabled', true)
                    ->orderBy('sort_order')
                    ->orderBy('id')
                    ->pluck('name', 'id')
                    ->all())
                ->searchable()
                ->preload()
                ->required(),
            DberpFilamentNumberFields::documentLineQuantityInput(
                TextInput::make('request_quantity')
                    ->label(__('dberp.fields.request_quantity'))
                    ->required(),
            ),
            TextInput::make('sort_order')
                ->label(__('dberp.fields.sort_order'))
                ->numeric()
                ->default(0)
                ->required(),
            Textarea::make('remark')
                ->label(__('dberp.fields.remark'))
                ->rows(2)
                ->columnSpanFull(),
        ], 'request_quantity', DberpDocumentLineUnitFormFields::resolveProductFromProductIdField('product_id'))));
    }

    public function table(Table $table): Table
    {
        return $table
            ->modifyQueryUsing(fn ($query) => $query->with(DberpDocumentLineSpecPresentation::eagerLoadsForDocumentLines(['baseUnit', 'auxiliaryUnit'])))
            ->recordTitleAttribute('product.name')
            ->defaultSort('sort_order', 'asc')
            ->columns([
                TextColumn::make('product.code')
                    ->label(__('dberp.fields.product_code')),
                TextColumn::make('product.name')
                    ->label(__('dberp.fields.product_name')),
                TextColumn::make('document_line_spec_summary')
                    ->label(__('dberp.fields.document_line_product_spec_combo'))
                    ->state(fn (Model $record): string => DberpDocumentLineSpecPresentation::lineSpecSummary($record))
                    ->wrap(),
                TextColumn::make('document_line_spec_code')
                    ->label(__('dberp.fields.document_line_spec_code'))
                    ->state(fn (Model $record): string => DberpDocumentLineSpecPresentation::lineSpecCode($record)),
                TextColumn::make('document_line_spec_abstract')
                    ->label(__('dberp.fields.document_line_spec_summary'))
                    ->state(fn (Model $record): string => DberpDocumentLineSpecPresentation::lineSpecAbstract($record))
                    ->wrap()
                    ->toggleable(isToggledHiddenByDefault: true),
                TextColumn::make('unit_name')
                    ->label(__('dberp.fields.document_line_entered_unit')),
                TextColumn::make('external_sku')
                    ->label(__('dberp.fields.external_sku'))
                    ->toggleable(isToggledHiddenByDefault: true),
                TextColumn::make('warehouse.name')
                    ->label(__('dberp.fields.warehouse')),
                TextColumn::make('source_type')
                    ->label(__('dberp.fields.source_type'))
                    ->formatStateUsing(fn (?string $state): string => PurchaseRequestSourceType::tryFrom((string) $state)?->label() ?? (string) $state),
                TextColumn::make('source_reference_no')
                    ->label(__('dberp.fields.source_reference_no'))
                    ->toggleable(isToggledHiddenByDefault: true),
                TextColumn::make('request_quantity')
                    ->label(__('dberp.fields.document_line_entered_quantity'))
                    ->formatStateUsing(fn ($state): string => DberpNumberFormatter::quantity($state)),
                TextColumn::make('document_line_primary_base_quantity')
                    ->label(__('dberp.fields.document_line_primary_base_quantity'))
                    ->state(fn ($record): string => DberpDocumentLinePresentation::primaryBaseQuantityDisplay($record))
                    ->toggleable(),
                TextColumn::make('document_line_conversion_snapshot')
                    ->label(__('dberp.fields.document_line_conversion_snapshot'))
                    ->state(fn ($record): string => DberpDocumentLinePresentation::conversionSnapshotLine($record))
                    ->wrap()
                    ->toggleable(isToggledHiddenByDefault: true),
                TextColumn::make('converted_quantity')
                    ->label(__('dberp.fields.converted_quantity'))
                    ->formatStateUsing(fn ($state): string => DberpNumberFormatter::quantity($state)),
                TextColumn::make('remaining_quantity')
                    ->label(__('dberp.fields.remaining_quantity'))
                    ->formatStateUsing(fn ($state): string => DberpNumberFormatter::quantity($state)),
                TextColumn::make('sort_order')
                    ->label(__('dberp.fields.sort_order')),
            ])
            ->headerActions([
                DberpDocumentLineBulkProductAddHeaderActions::purchaseRequestItems(
                    fn (): Model => $this->getOwnerRecord(),
                ),
                CreateAction::make()
                    ->mutateDataUsing(fn (array $data): array => DberpLineProductSkuFormFields::finalizeLineSkuFormData($this->fillIntegrationFields($data)))
                    ->visible(fn (): bool => in_array($this->getOwnerRecord()->status, [PurchaseRequestStatus::Draft->value, PurchaseRequestStatus::Pending->value], true)),
            ])
            ->recordActions([
                EditAction::make()
                    ->mutateDataUsing(fn (array $data): array => DberpLineProductSkuFormFields::finalizeLineSkuFormData($this->fillIntegrationFields($data)))
                    ->visible(fn (): bool => in_array($this->getOwnerRecord()->status, [PurchaseRequestStatus::Draft->value, PurchaseRequestStatus::Pending->value], true)),
                DeleteAction::make()
                    ->visible(fn (): bool => in_array($this->getOwnerRecord()->status, [PurchaseRequestStatus::Draft->value, PurchaseRequestStatus::Pending->value], true)),
            ]);
    }

    /**
     * @param  array<string, mixed>  $data
     * @return array<string, mixed>
     */
    private function fillIntegrationFields(array $data): array
    {
        $product = isset($data['product_id'])
            ? DberpProduct::query()->find((int) $data['product_id'])
            : null;

        $data['external_product_id'] = $data['external_product_id'] ?? $product?->external_product_id;
        $data['external_sku'] = filled($data['external_sku'] ?? null)
            ? (string) $data['external_sku']
            : $product?->external_sku;

        return $data;
    }
}
