<?php

namespace App\Filament\Resources\Consignments\Tables;

use App\Filament\Concerns\HasDocumentActions;
use App\Models\Consignment;
use App\Models\ConsignmentStatusHistory;
use App\Models\StockMovement;
use Filament\Notifications\Notification;
use Filament\Actions\Action;
use Filament\Actions\ActionGroup;
use Filament\Actions\DeleteAction;
use Filament\Actions\EditAction;
use Filament\Actions\BulkActionGroup;
use Filament\Actions\DeleteBulkAction;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Filters\SelectFilter;
use Filament\Tables\Table;

class ConsignmentsTable
{
    public static function configure(Table $table): Table
    {
        return $table
            ->modifyQueryUsing(fn ($query) =>
                $query->select([
                    'id',
                    'shipment_id',
                    'house_waybill_no',
                    'flight_no',
                    'container_no',
                    'customer_name',
                    'phone',
                    'description',
                    'destination',
                    'pcs',
                    'actual_weight_kgs',
                    'cbm',
                    'extra_charge_usd',
                    'amount_usd',
                    'amount_kes',
                    'status',
                    'collected_at',
                    'created_at',
                ])
                ->with([
                    'shipment:id,type,reference,origin,destination',
                ])
            )
            ->paginated([15, 25, 50])
            ->defaultPaginationPageOption(15)
            ->columns([

                TextColumn::make('reference')
                    ->label('Ref.')
                    ->getStateUsing(fn (Consignment $record): string =>
                        $record->flight_no
                            ?? $record->container_no
                            ?? $record->house_waybill_no
                            ?? "CON-{$record->id}"
                    )
                    ->description(fn (Consignment $record): ?string =>
                        $record->flight_no && $record->house_waybill_no
                            ? 'HAWB: ' . $record->house_waybill_no
                            : null
                    )
                    ->weight('bold')
                    ->searchable(query: fn ($query, string $search) =>
                        $query->where('flight_no', 'like', "%{$search}%")
                              ->orWhere('house_waybill_no', 'like', "%{$search}%")
                              ->orWhere('container_no', 'like', "%{$search}%")
                    ),

                TextColumn::make('customer_name')
                    ->label('Consignee')
                    ->searchable()
                    ->sortable(),

                TextColumn::make('phone')
                    ->searchable(),

                TextColumn::make('shipment.reference')
                    ->label('Shipment')
                    ->searchable(),

                TextColumn::make('shipment.type')
                    ->label('Type')
                    ->badge()
                    ->color(fn (string $state): string => match ($state) {
                        'air'   => 'info',
                        'sea'   => 'warning',
                        default => 'gray',
                    }),

                TextColumn::make('description')
                    ->limit(30)
                    ->placeholder('—'),

                TextColumn::make('pcs')
                    ->label('PCS/CTN')
                    ->alignCenter(),

                TextColumn::make('actual_weight_kgs')
                    ->label('KGS')
                    ->placeholder('—')
                    ->alignCenter()
                    ->toggleable(isToggledHiddenByDefault: true),

                TextColumn::make('cbm')
                    ->label('CBM')
                    ->placeholder('—')
                    ->alignCenter()
                    ->toggleable(isToggledHiddenByDefault: true),

                TextColumn::make('extra_charge_usd')
                    ->label('Extra $')
                    ->formatStateUsing(fn ($state) =>
                        $state > 0 ? '$ ' . number_format($state, 2) : '—'
                    )
                    ->alignRight()
                    ->color('danger')
                    ->toggleable(isToggledHiddenByDefault: true),

                TextColumn::make('amount_kes')
                    ->label('Amount (KES)')
                    ->formatStateUsing(fn ($state) =>
                        'KES ' . number_format($state, 2)
                    )
                    ->weight('bold')
                    ->alignRight(),

                TextColumn::make('status')
                    ->badge()
                    ->color(fn (string $state): string => match ($state) {
                        'in_transit'       => 'info',
                        'in_warehouse'     => 'warning',
                        'ready_for_pickup' => 'success',
                        'delivered'        => 'gray',
                        default            => 'gray',
                    })
                    ->formatStateUsing(fn (string $state): string =>
                        ucwords(str_replace('_', ' ', $state))
                    ),

                TextColumn::make('created_at')
                    ->label('Created')
                    ->dateTime('M d, Y')
                    ->sortable()
                    ->toggleable(isToggledHiddenByDefault: true),
            ])
            ->filters([
                SelectFilter::make('status')
                    ->options(Consignment::statusOptions()),

                SelectFilter::make('shipment')
                    ->relationship('shipment', 'reference'),
            ])
            ->actions([
                EditAction::make(),

                // ── Status actions ────────────────────────────────
                ActionGroup::make([

                    Action::make('mark_in_warehouse')
                        ->label('Mark In Warehouse')
                        ->icon('heroicon-o-building-storefront')
                        ->color('warning')
                        ->hidden(fn (Consignment $r): bool =>
                            $r->status !== 'in_transit'
                        )
                        ->action(function (Consignment $r): void {
                            $r->update(['status' => 'in_warehouse']);

                            StockMovement::create([
                                'consignment_id' => $r->id,
                                'type'           => 'IN',
                                'notes'          => 'Arrived in warehouse',
                                'moved_by'       => auth()->id(),
                                'moved_at'       => now(),
                            ]);

                            ConsignmentStatusHistory::create([
                                'consignment_id' => $r->id,
                                'status'         => 'in_warehouse',
                                'note'           => 'Goods arrived in warehouse',
                                'changed_by'     => auth()->id(),
                            ]);

                            Notification::make()
                                ->title("{$r->customer_name} — in warehouse")
                                ->success()
                                ->send();
                        }),

                    Action::make('mark_ready')
                        ->label('Mark Ready for Pickup')
                        ->icon('heroicon-o-inbox-arrow-down')
                        ->color('success')
                        ->hidden(fn (Consignment $r): bool =>
                            $r->status !== 'in_warehouse'
                        )
                        ->action(function (Consignment $r): void {
                            $r->update(['status' => 'ready_for_pickup']);

                            ConsignmentStatusHistory::create([
                                'consignment_id' => $r->id,
                                'status'         => 'ready_for_pickup',
                                'note'           => 'Payment confirmed — cleared for pickup',
                                'changed_by'     => auth()->id(),
                            ]);

                            Notification::make()
                                ->title("{$r->customer_name} — ready for pickup")
                                ->success()
                                ->send();
                        }),

                    Action::make('undo_status')
                        ->label('Undo Last Status')
                        ->icon('heroicon-o-arrow-uturn-left')
                        ->color('danger')
                        ->visible(fn (Consignment $r): bool =>
                            $r->status !== 'in_transit'
                        )
                        ->requiresConfirmation()
                        ->modalHeading('Undo last status?')
                        ->modalDescription('This will revert to the previous status.')
                        ->action(function (Consignment $r): void {
                            $previous = match ($r->status) {
                                'in_warehouse'     => 'in_transit',
                                'ready_for_pickup' => 'in_warehouse',
                                'delivered'        => 'ready_for_pickup',
                                default            => 'in_transit',
                            };

                            $r->update([
                                'status'       => $previous,
                                'collected_at' => null,
                                'collected_by' => null,
                            ]);

                            Notification::make()
                                ->title('Status reverted to: ' . ucwords(str_replace('_', ' ', $previous)))
                                ->warning()
                                ->send();
                        }),

                ])
                ->label('Status')
                ->icon('heroicon-o-arrow-path')
                ->color('primary')
                ->button(),

                // ── Documents ─────────────────────────────────────
                // Uses HasDocumentActions trait
                ActionGroup::make(
                    self::getDocumentActions()
                )
                ->label('Actions')
                ->icon('heroicon-o-ellipsis-vertical')
                ->color('gray')
                ->button(),

                DeleteAction::make(),
            ])
            ->bulkActions([
                BulkActionGroup::make([
                    DeleteBulkAction::make(),
                ]),
            ])
            ->defaultSort('created_at', 'desc');
    }

    // ── Document actions (invoice + delivery note) ────────────────
    // Pulled from HasDocumentActions trait but called statically
    // since this is not a Filament component class

    private static function getDocumentActions(): array
    {
        return [
 
            Action::make('generate_invoice')
                ->label('Generate / View Invoice')
                ->icon('heroicon-o-document-currency-dollar')
                ->color('success')
                ->visible(fn (): bool =>
                    auth()->user()?->hasRole(['super_admin', 'admin']) ?? false
                )
                ->requiresConfirmation()
                ->modalHeading('Generate Invoice')
                ->modalDescription(
                    'This will calculate the invoice from current rates. ' .
                    'Any existing invoice will be replaced.'
                )
                ->modalSubmitActionLabel('Generate')
                ->action(function (\App\Models\Consignment $record): void {
                    \App\Models\Invoice::where('consignment_id', $record->id)->delete();
                    $record->unsetRelation('invoice');
                    $record->unsetRelation('shipment');
 
                    app(\App\Services\InvoiceService::class)
                        ->generateForConsignment($record);
 
                    \Filament\Notifications\Notification::make()
                        ->title('Invoice generated successfully')
                        ->success()
                        ->send();
                })
                ->successRedirectUrl(fn (\App\Models\Consignment $record): string =>
                    route('documents.print', ['invoice', $record->id])
                ),
 
            Action::make('generate_dn')
                ->label('Generate / View Delivery Note')
                ->icon('heroicon-o-clipboard-document-check')
                ->color('info')
                ->requiresConfirmation()
                ->modalHeading('Generate Delivery Note')
                ->modalDescription('This will generate (or replace) the delivery note.')
                ->modalSubmitActionLabel('Generate')
                ->action(function (\App\Models\Consignment $record): void {
                    \App\Models\DeliveryNote::where('consignment_id', $record->id)->delete();
                    $record->unsetRelation('deliveryNote');
                    $record->unsetRelation('shipment');
 
                    app(\App\Services\InvoiceService::class)
                        ->generateDeliveryNote($record);
 
                    \Filament\Notifications\Notification::make()
                        ->title('Delivery note generated successfully')
                        ->success()
                        ->send();
                })
                ->successRedirectUrl(fn (\App\Models\Consignment $record): string =>
                    route('documents.print', ['delivery-note', $record->id])
                ),
        ];
    }
}