<?php

declare(strict_types=1);

namespace App\Filament\Resources\DberpPurchaseInquiries\RelationManagers;

use App\Business\Purchase\Enums\PurchaseInquiryQuoteStatus;
use App\Business\Purchase\Enums\PurchaseInquiryStatus;
use App\Business\Purchase\PurchaseInquiryQuoteService;
use App\Filament\Support\DberpFilamentNumberFields;
use App\Models\DberpPurchaseInquiry;
use App\Models\DberpPurchaseInquiryItem;
use App\Models\DberpPurchaseInquiryQuote;
use App\Models\DberpSupplier;
use App\Support\DberpLineProductSkuFormFields;
use App\Support\DberpNumberFormatter;
use Filament\Actions\Action;
use Filament\Actions\CreateAction;
use Filament\Actions\DeleteAction;
use Filament\Actions\EditAction;
use Filament\Forms\Components\DatePicker;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\Textarea;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\Toggle;
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\IconColumn;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Model;

class QuotesRelationManager extends RelationManager
{
    protected static string $relationship = 'quotes';

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

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

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

    public function form(Schema $schema): Schema
    {
        return $schema->components([
            Select::make('purchase_inquiry_item_id')
                ->label(__('dberp.fields.purchase_inquiry_item'))
                ->options(fn (): array => $this->inquiryItemOptions())
                ->searchable()
                ->preload()
                ->live()
                ->afterStateUpdated(function (Set $set, Get $get): void {
                    $itemId = (int) ($get('purchase_inquiry_item_id') ?? 0);

                    if ($itemId <= 0) {
                        return;
                    }

                    $item = DberpPurchaseInquiryItem::query()
                        ->with('purchaseRequestItem')
                        ->find($itemId);

                    if ($item?->purchase_request_item_id) {
                        DberpLineProductSkuFormFields::applyFromPurchaseRequestItemSelection(
                            $set,
                            (int) $item->purchase_request_item_id,
                        );
                    }
                })
                ->required(),
            Select::make('supplier_id')
                ->label(__('dberp.fields.supplier'))
                ->options(fn (): array => DberpSupplier::query()->where('is_enabled', true)->orderBy('sort_order')->orderBy('id')->pluck('name', 'id')->all())
                ->searchable()
                ->preload()
                ->required(),
            DatePicker::make('quote_date')
                ->label(__('dberp.fields.quote_date'))
                ->default(fn () => now()->toDateString())
                ->required(),
            DatePicker::make('valid_until')
                ->label(__('dberp.fields.valid_until')),
            DberpFilamentNumberFields::moneyInput(
                TextInput::make('unit_price')
                    ->label(__('dberp.fields.unit_price'))
                    ->required(),
                withHelperText: false,
                minValue: 0.0,
            ),
            DberpFilamentNumberFields::quantityInput(
                TextInput::make('min_order_quantity')
                    ->label(__('dberp.fields.min_order_quantity'))
                    ->default(0),
                withHelperText: false,
                minValue: 0.0,
            ),
            TextInput::make('lead_time_days')
                ->label(__('dberp.fields.lead_time_days'))
                ->numeric()
                ->minValue(0),
            TextInput::make('tax_rate')
                ->label(__('dberp.fields.tax_rate'))
                ->numeric()
                ->minValue(0)
                ->default(0),
            Toggle::make('is_tax_included')
                ->label(__('dberp.fields.is_tax_included')),
            Toggle::make('is_recommended')
                ->label(__('dberp.fields.is_recommended')),
            Textarea::make('quote_note')
                ->label(__('dberp.fields.quote_note'))
                ->rows(2)
                ->columnSpanFull(),
            Textarea::make('remark')
                ->label(__('dberp.fields.remark'))
                ->rows(2)
                ->columnSpanFull(),
        ]);
    }

    public function table(Table $table): Table
    {
        return $table
            ->defaultSort('quote_date', 'desc')
            ->columns([
                TextColumn::make('code')
                    ->label(__('dberp.fields.purchase_inquiry_quote_code')),
                TextColumn::make('purchaseInquiryItem.product.name')
                    ->label(__('dberp.fields.product')),
                TextColumn::make('supplier_name_snapshot')
                    ->label(__('dberp.fields.supplier')),
                TextColumn::make('unit_price')
                    ->label(__('dberp.fields.unit_price'))
                    ->formatStateUsing(fn ($state): string => DberpNumberFormatter::price($state)),
                IconColumn::make('is_recommended')
                    ->label(__('dberp.fields.is_recommended'))
                    ->boolean(),
                TextColumn::make('status')
                    ->label(__('dberp.fields.status'))
                    ->badge()
                    ->formatStateUsing(fn (?string $state): string => PurchaseInquiryQuoteStatus::tryFrom((string) $state)?->label() ?? (string) $state),
                TextColumn::make('quote_date')
                    ->label(__('dberp.fields.quote_date'))
                    ->date(),
                TextColumn::make('valid_until')
                    ->label(__('dberp.fields.valid_until'))
                    ->date(),
            ])
            ->headerActions([
                CreateAction::make()
                    ->visible(fn (): bool => $this->canManageQuotes())
                    ->mutateFormDataUsing(function (array $data): array {
                        $item = DberpPurchaseInquiryItem::query()->findOrFail((int) $data['purchase_inquiry_item_id']);

                        $data['purchase_request_item_id'] = $item->purchase_request_item_id;

                        return $data;
                    })
                    ->using(function (array $data): Model {
                        return app(PurchaseInquiryQuoteService::class)->createQuote($data);
                    }),
            ])
            ->recordActions([
                EditAction::make()
                    ->visible(fn (): bool => $this->canManageQuotes())
                    ->using(function (DberpPurchaseInquiryQuote $record, array $data): Model {
                        return app(PurchaseInquiryQuoteService::class)->updateQuote($record, $data);
                    }),
                Action::make('mark_recommended')
                    ->label(__('dberp.actions.mark_recommended'))
                    ->requiresConfirmation()
                    ->visible(fn (DberpPurchaseInquiryQuote $record): bool => $this->canManageQuotes()
                        && $record->status === PurchaseInquiryQuoteStatus::Active->value
                        && ! $record->is_recommended)
                    ->action(function (DberpPurchaseInquiryQuote $record): void {
                        app(PurchaseInquiryQuoteService::class)->markRecommended($record);
                    }),
                Action::make('invalidate')
                    ->label(__('dberp.actions.invalidate_quote'))
                    ->requiresConfirmation()
                    ->visible(fn (DberpPurchaseInquiryQuote $record): bool => $this->canManageQuotes()
                        && $record->status !== PurchaseInquiryQuoteStatus::Invalidated->value)
                    ->form([
                        Textarea::make('reason')
                            ->label(__('dberp.fields.invalidate_reason'))
                            ->rows(3),
                    ])
                    ->action(function (DberpPurchaseInquiryQuote $record, array $data): void {
                        app(PurchaseInquiryQuoteService::class)->invalidate($record, $data['reason'] ?? null);
                    }),
                DeleteAction::make()
                    ->visible(fn (): bool => false),
            ]);
    }

    /**
     * @return array<int, string>
     */
    private function inquiryItemOptions(): array
    {
        $owner = $this->getOwnerRecord();

        if (! $owner instanceof DberpPurchaseInquiry) {
            return [];
        }

        return $owner->items()
            ->with('product')
            ->orderBy('sort_order')
            ->get()
            ->mapWithKeys(fn (DberpPurchaseInquiryItem $item): array => [
                $item->getKey() => trim(($item->product?->name ?? '-').' / '.DberpNumberFormatter::quantity($item->inquiry_quantity)),
            ])
            ->all();
    }

    private function canManageQuotes(): bool
    {
        $owner = $this->getOwnerRecord();

        return $owner instanceof DberpPurchaseInquiry
            && $owner->status === PurchaseInquiryStatus::Open->value;
    }
}
