<?php

namespace App\Filament\Office\Resources;

use Filament\Forms;
use Filament\Tables;
use App\Enums\BLTypes;
use Filament\Forms\Form;
use Filament\Tables\Table;
use App\Models\Billoflading;
use Filament\Resources\Resource;
use Filament\Forms\Components\Grid;
use Filament\Tables\Actions\Action;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\Section;
use Filament\Forms\Components\Repeater;
use Illuminate\Database\Eloquent\Model;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\DatePicker;
use Filament\Forms\Components\RichEditor;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope;
use App\Filament\Office\Resources\BillofladingResource\Pages;
use App\Filament\Office\Resources\CompanyResource\CompanyForms;
use App\Filament\Office\Resources\BillofladingResource\RelationManagers;

class BillofladingResource extends Resource
{
    protected static ?string $model = Billoflading::class;

    protected static ?string $slug = 'shipping/billofladings';

    protected static ?string $navigationGroup = 'Shipping';
    protected static ?string $navigationIcon = 'heroicon-o-rectangle-stack';
    protected static ?string $navigationLabel = 'Bill Of Lading';
    protected static ?string $modelLabel = 'Bill Of Lading';

    public static function form(Form $form): Form
    {
        return $form
            ->schema([
            Forms\Components\Group::make()
            ->schema([
                Section::make('General')
                    // ->description('Description')
                    ->schema([
                    TextInput::make('bl_no')->label('Bill Of Leading Number')->helperText('Bill Of Leading number needs to be unique')->required()->columnSpan(2),
                    DatePicker::make('etd')->label('Estimated time of departure')->default('+1days'),
                    DatePicker::make('eta')->label('Estimated time of arrival')->default('+7days'),
                ])->columns(2),
    
                // Vessel 
                Section::make('Vessel')
                ->description('Write voyage details')
                ->schema([
                    Select::make('pre_carriage_vessel')
                        ->label('Pre-carriage Vessel')
                        // ->options(\App\Models\Vessel::all()->pluck('name', 'id'))
                        ->relationship('pre_carriage_vessel_data', 'name', fn (Builder $query) => $query->withTrashed())
                        ->searchable()
                        ->reactive()
                        ->createOptionForm([
                            Self::getVesselAddForm()
                        ]),
                    TextInput::make('voy_no_pre_carriage')
                        ->label('Voyage No (Pre-carriage)'),
                    Select::make('ocean_vessel')
                        ->label('Ocean Vessel')
                        // ->options(\App\Models\Vessel::all()->pluck('name', 'id'))
                        ->relationship('ocean_vessel_data', 'name', fn (Builder $query) => $query->withTrashed())
                        ->searchable()
                        ->reactive()
                        ->createOptionForm([
                            Self::getVesselAddForm()
                        ]),
                    TextInput::make('voy_no_destination')->label('Voyage No (Destination)'),

                    // Discharge / Destination
                    Select::make('place_of_receipt')
                        ->label('Place of Receipt (POR)')
                        // ->options(\App\Models\Port::all()->pluck('name', 'id'))
                        ->relationship('place_of_receipt_data', 'name', fn (Builder $query) => $query->withTrashed())
                        ->searchable()
                        ->reactive()
                        ->createOptionForm([
                            Self::getPortAddForm()
                        ]),
                    Select::make('place_of_loading')
                        ->label('Place of Loading (POL)')
                        // ->options(\App\Models\Port::all()->pluck('name', 'id'))
                        ->relationship('place_of_loading_data', 'name', fn (Builder $query) => $query->withTrashed())
                        ->searchable()
                        ->reactive()
                        ->createOptionForm([
                            Self::getPortAddForm()
                        ]),
                    Select::make('port_of_discharge')
                        ->label('Port of Discharge (POD)')
                        // ->options(\App\Models\Port::all()->pluck('name', 'id'))
                        ->relationship('port_of_discharge_data', 'name', fn (Builder $query) => $query->withTrashed())
                        ->searchable()
                        ->reactive()
                        ->createOptionForm([
                            Self::getPortAddForm()
                        ]),
                    Select::make('final_destination')
                        ->label('Final Destination')
                        // ->options(\App\Models\Port::all()->pluck('name', 'id'))
                        ->relationship('final_destination_data', 'name', fn (Builder $query) => $query->withTrashed())
                        ->searchable()
                        ->reactive()
                        ->createOptionForm([
                            Self::getPortAddForm()
                        ]),
                ])->columns(2),

                // Container Info 
                Section::make('Container Info')
                // ->description('Description')
                ->schema([
                    TextInput::make('weight'),
                    TextInput::make('net_weight')->label('Net Weight'),
                    TextInput::make('measurement'),
                    TextInput::make('qty')->label('Quantity'),
                    RichEditor::make('container_info')->columnSpan(4),
                    RichEditor::make('discription_of_goods')->columnSpan(4),
                    RichEditor::make('discription_of_goods2')->label('Discription of goods 2')->columnSpan(4),
                ])->columns(4),

                // Frieght Info
                Section::make('Frieght Info')
                // ->description('Description')
                ->schema([
                    Select::make('freight_type')
                        ->options([
                            'prepaid' => 'Prepaid', 
                            'postpaid' => 'Postpaid', 
                            'collect' => 'Collect'
                            ])
                        ->default('prepaid')
                        ->columnSpan(3),
                    RichEditor::make('freight_and_charges')->columnSpan(3),
                    TextInput::make('revenue_tons'),
                    TextInput::make('rate')->numeric(),
                    TextInput::make('prepaid'),
                    TextInput::make('collect'),
                    TextInput::make('ex_rate')->label('Exchange Rate (USD)')->numeric(),
                    TextInput::make('prepaid2')->label('Prepaid (2)'),
                ])->columns(3),

                Repeater::make('bl_containers')->label('Containers')
                ->schema([
                    Select::make('container_id')
                    // ->options(\App\Models\Container::all()->pluck('container_no', 'id'))
                    ->relationship('container', 'container_no', fn (Builder $query) => $query->withTrashed())
                    ->searchable()
                    ->reactive()
                    ->createOptionForm([
                        Self::getContainerAddForm()
                    ]),
                    TextInput::make('seal_no')->label('Seal number')->required(),
                    TextInput::make('pack_qty')->label('Qty (pcs/pck)'),
                    TextInput::make('gross_weight')->label('Gross Weight'),
                    TextInput::make('net_weight')->label('Net Weight'),
                    TextInput::make('measurement')->label('Measurement'),
                ])
                ->relationship()
                ->cloneable()
                // ->orderable()
                ->minItems(1)
                ->columns(2)
                ->createItemButtonLabel('Add Another Container')            
            ])
            ->columnSpan(['lg' => 2]),

            Forms\Components\Group::make()
            ->schema([
                Section::make('Status')
                // ->description('Description')
                ->schema([
                    Select::make('bl_type')
                        ->label('BL Type')
                        ->options(BLTypes::class)->default('draft'),
                    Select::make('bl_status')
                        ->label('BL Status')
                        ->options(\App\Models\Status::all()->pluck('status', 'id')),
                        // ->options([
                        //     'On the way' => 'On the way', 
                        //     'On bord' => 'On bord', 
                        //     'Delivered' => 'Delivered', 
                        //     'Empty Returned' => 'Empty Returned', 
                        //     'Discharged' => 'Discharged', 
                        //     'Waiting to load' => 'Waiting to load', 
                        //     'Waiting to sail' => 'Waiting to sail', 
                        //     'Waiting for Discharge' => 'Waiting for Discharge', 
                        //     'Waiting for delivered' => 'Waiting for delivered', 
                        // ])
                        // ->default('Waiting to sail'),
                    TextInput::make('container_tues')->numeric(),
                ]),
                    
                // customer
                Section::make('Customer')
                // ->description('Assign customer')
                ->schema([
                    Select::make('shipper')
                        ->label('Shipper')
                        // ->options(\App\Models\Company::all()->pluck('name', 'id'))
                        ->relationship('shipper_data', 'name', fn (Builder $query) => $query->withTrashed())
                        ->getOptionLabelFromRecordUsing(fn (Model $record) => "{$record->name} ({$record->code})")
                        ->searchable(['name', 'code', 'website', 'primary_email'])
                        ->reactive()
                        ->createOptionForm([
                            CompanyForms::getAddForm()
                        ]),
                    Select::make('consignee')
                        ->label('Consignee')
                        // ->options(\App\Models\Company::all()->pluck('name', 'id'))
                        ->relationship('consignee_data', 'name', fn (Builder $query) => $query->withTrashed())
                        ->getOptionLabelFromRecordUsing(fn (Model $record) => "{$record->name} ({$record->code})")
                        ->searchable(['name', 'code', 'website', 'primary_email'])
                        ->reactive()
                        ->createOptionForm([
                            CompanyForms::getAddForm()
                        ]),
                    Select::make('notify_party')
                        ->label('1st Notify Party')
                        // ->options(\App\Models\Company::all()->pluck('name', 'id'))
                        ->relationship('notify_party_data', 'name', fn (Builder $query) => $query->withTrashed())
                        ->getOptionLabelFromRecordUsing(fn (Model $record) => "{$record->name} ({$record->code})")
                        ->searchable(['name', 'code', 'website', 'primary_email'])
                        ->reactive()
                        ->createOptionForm([
                            CompanyForms::getAddForm()
                        ]),
                    Select::make('notify_party2')
                        ->label('2nd Notify Party')
                        // ->options(\App\Models\Company::all()->pluck('name', 'id'))
                        ->relationship('notify_party2_data', 'name', fn (Builder $query) => $query->withTrashed())
                        ->getOptionLabelFromRecordUsing(fn (Model $record) => "{$record->name} ({$record->code})")
                        ->searchable(['name', 'code', 'website', 'primary_email'])
                        ->reactive()
                        ->createOptionForm([
                            CompanyForms::getAddForm()
                        ]),
                    Select::make('delivery_agent')
                        ->label('Delivery Agent')
                        // ->options(\App\Models\Company::all()->pluck('name', 'id'))
                        ->relationship('delivery_agent_data', 'name', fn (Builder $query) => $query->withTrashed())
                        ->getOptionLabelFromRecordUsing(fn (Model $record) => "{$record->name} ({$record->code})")
                        ->searchable(['name', 'code', 'website', 'primary_email'])
                        ->reactive()
                        ->createOptionForm([
                            CompanyForms::getAddForm()
                        ]),
                ]),

                // Ref. 
                Section::make('Reference')
                // ->description('Description')
                ->schema([
                    TextInput::make('booking_ref_no')->label('Booking reference number'),
                    TextInput::make('shipper_ref')->label('Shipper reference number'),
                    Select::make('original_bl')->label('Number of Original BL(s)')->options([0, 1, 2, 3])->default(1),
                ]),

                // Payment Info
                Section::make('Payment Info')
                // ->description('Description')
                ->schema([
                    Select::make('company_id')
                        ->label('Invoice To (Company)')
                        // ->options(\App\Models\Port::all()->pluck('name', 'id'))
                        ->relationship('company_data', 'name', fn (Builder $query) => $query->withTrashed())
                        ->getOptionLabelFromRecordUsing(fn (Model $record) => "{$record->name} ({$record->code})")
                        ->searchable(['name', 'code', 'website', 'primary_email'])
                        ->reactive()
                        ->createOptionForm([
                            CompanyForms::getAddForm()
                        ]),

                    Select::make('payable_at')
                        ->label('Payable At')
                        // ->options(\App\Models\Port::all()->pluck('name', 'id'))
                        ->relationship('payable_at_data', 'name', fn (Builder $query) => $query->withTrashed())
                        ->searchable()
                        ->reactive()
                        ->createOptionForm([
                            Self::getPortAddForm()
                        ]),
                    Select::make('place_issue')
                        ->label('Place Issue')
                        // ->options(\App\Models\Port::all()->pluck('name', 'id'))
                        ->relationship('place_issue_data', 'name', fn (Builder $query) => $query->withTrashed())
                        ->searchable()
                        ->reactive()
                        ->createOptionForm([
                            Self::getPortAddForm()
                        ]),
                    DatePicker::make('issue_date')->default(today()),
                ]),
                
                // Hidden 
                Section::make('Restricted')
                ->description('Official Use Only')
                ->schema([
                    // Select::make('entry_by')
                    //     ->options(\App\Models\User::all()->pluck('name', 'id'))
                    //     ->searchable(),
                    // Select::make('last_updated_by')
                    //     ->options(\App\Models\User::all()->pluck('name', 'id'))
                    //     ->searchable(),
                    // Select::make('deleted_by')
                    //     ->options(\App\Models\User::all()->pluck('name', 'id'))
                    //     ->searchable(),
                    Select::make('warehouse_id')
                        ->label('Warehouse/Depot')
                        // ->options(\App\Models\Port::all()->pluck('name', 'id'))
                        ->relationship('warehouse_data', 'name', fn (Builder $query) => $query->withTrashed())
                        ->getOptionLabelFromRecordUsing(fn (Model $record) => "{$record->name} ({$record->code})")
                        ->searchable(['name', 'code', 'website', 'primary_email'])
                        ->reactive()
                        ->createOptionForm([
                            CompanyForms::getAddForm()
                        ]),
                ]),
                
                // Hidden 
                Section::make('Delivery Order')
                ->description('Official Use Only')
                ->schema([
                    DatePicker::make('do_issued_at')->label('DO Issued At')->default(today()),
                    TextInput::make('do_online_id')->label('Online DO ID')->numeric(),
                    TextInput::make('do_cnf_name')->label('C&F Name'),
                    TextInput::make('do_cnf_license')->label('C&F License'),
                ]),
            ])
            ->columnSpan(['lg' => 1]),
        ])
        ->columns(3);
    }

    static protected function getPortAddForm() : Grid {
        return Grid::make('Add New Port')->schema([
            TextInput::make('name')
                ->helperText('Enter full name of port here (no iso or country code).')
                ->required()
                ->minLength(2)
                ->maxLength(100),
            Select::make('country_id')
                ->relationship('country', 'name')
                ->searchable()
                ->required(),
            TextInput::make('latitude')->numeric(),
            TextInput::make('longitude')->numeric(),
            TextInput::make('iso')->label('ISO')
                ->helperText('ISO is the unique identifier for a port.')
                ->minLength(2)
                ->maxLength(3)
                ->required(),
            Select::make('type')
                ->options([
                    'inland' => 'Inland',
                    'dry' => 'Dry',
                    'fishing' => 'Fishing',
                    'warm-water' => 'Warm Water',
                    'seaports' => 'Seaports',
                ]),
        ])->columns(2);
    }

    static protected function getVesselAddForm() : Grid {
        return Grid::make('Add New Delivery Agent')->schema([
            TextInput::make('name')
                ->unique(ignorable: fn ($record) => $record)
                ->helperText('Write new vessel name here')
                ->minLength(3)
                ->maxLength(100),
            TextInput::make('capacity')
                ->helperText('Capacity with tues')
                ->minLength(1),
            Select::make('route_start')
                ->label('Starting Port')
                ->relationship('port_start', 'name')
                ->searchable(),
            Select::make('route_end')
                ->label('Destination Port')
                ->relationship('port_end', 'name')
                ->searchable(),
        ])->columns(2);
    }

    static protected function getContainerAddForm() : Grid {
        return Grid::make('Add New Delivery Agent')->schema([
            TextInput::make('container_no')
                ->unique(ignorable: fn ($record) => $record)
                ->required()
                ->helperText('Container number needs to be unique')
                ->maxLength(25)
                ->columnSpan(2),
            TextInput::make('size')->label('Container Size')->maxLength(25),
            TextInput::make('type')->maxLength(25),
        ])->columns(2);
    }

    public static function table(Table $table): Table
    {
        return $table
            ->columns([
                // Tables\Columns\TextColumn::make('company_data.name')
                //     ->numeric()
                //     ->sortable(),
                // Tables\Columns\TextColumn::make('warehouse_data.name')
                //     ->numeric()
                //     ->sortable(),
                // Tables\Columns\TextColumn::make('shipper_data.name')
                //     ->numeric()
                //     ->sortable(),
                // Tables\Columns\TextColumn::make('consignee')
                //     ->numeric()
                //     ->sortable(),
                // Tables\Columns\TextColumn::make('notify_party')
                //     ->numeric()
                //     ->sortable(),
                // Tables\Columns\TextColumn::make('delivery_agent')
                //     ->numeric()
                //     ->sortable(),
                // Tables\Columns\TextColumn::make('pre_carriage_vessel')
                //     ->numeric()
                //     ->sortable(),
                Tables\Columns\TextColumn::make('bl_no')
                    ->label('BL Number')
                    ->description(fn (Billoflading $record): string => 'ETA: '.$record->etd . ' - ETA: '.$record->eta)
                    ->searchable(),
                // Tables\Columns\TextColumn::make('place_of_receipt')
                //     ->numeric()
                //     ->sortable(),
                Tables\Columns\TextColumn::make('ocean_vessel_data.name')
                    ->label('Vessel')
                    ->description(fn (Billoflading $record): string => 'Pre-carriage: '.$record->pre_carriage_vessel_data->name)
                    ->numeric()
                    ->sortable(),
                // Tables\Columns\TextColumn::make('place_of_loading')
                //     ->numeric()
                //     ->sortable(),
                Tables\Columns\TextColumn::make('port_of_discharge_data.name')
                    ->label('Discharge')
                    ->description(fn (Billoflading $record): string => 'Final Destination: '.$record->final_destination_data->name)
                    ->numeric()
                    ->sortable(),
                // Tables\Columns\TextColumn::make('final_destination')
                //     ->numeric()
                //     ->sortable(),
                // Tables\Columns\TextColumn::make('payable_at')
                //     ->numeric()
                //     ->sortable(),
                // Tables\Columns\TextColumn::make('place_issue')
                //     ->numeric()
                //     ->sortable(),
                // Tables\Columns\TextColumn::make('entry_by')
                //     ->numeric()
                //     ->sortable(),
                // Tables\Columns\TextColumn::make('last_updated_by')
                //     ->numeric()
                //     ->sortable(),
                // Tables\Columns\TextColumn::make('deleted_by')
                //     ->numeric()
                //     ->sortable(),
                // Tables\Columns\TextColumn::make('etd')
                //     ->date()
                //     ->sortable(),
                // Tables\Columns\TextColumn::make('eta')
                //     ->date()
                //     ->sortable(),
                Tables\Columns\TextColumn::make('container_tues')
                    ->label('Tues.')
                    ->description(fn (Billoflading $record): string => 'Issued at: '.\Carbon\Carbon::parse($record->issue_date)->diffForHumans())
                    ->numeric()
                    ->sortable(),
                // Tables\Columns\TextColumn::make('issue_date')
                //     ->date()->since()
                //     ->sortable(),
                // Tables\Columns\TextColumn::make('voy_no_pre_carriage')
                //     ->searchable(),
                // Tables\Columns\TextColumn::make('voy_no_destination')
                //     ->searchable(),
                // Tables\Columns\TextColumn::make('booking_ref_no')
                //     ->searchable(),
                // Tables\Columns\TextColumn::make('shipper_ref')
                //     ->searchable(),
                // Tables\Columns\TextColumn::make('container_info')
                //     ->searchable(),
                // Tables\Columns\TextColumn::make('qty')
                //     ->searchable(),
                // Tables\Columns\TextColumn::make('weight')
                //     ->searchable(),
                // Tables\Columns\TextColumn::make('nett_weight')
                //     ->searchable(),
                // Tables\Columns\TextColumn::make('measurement')
                //     ->searchable(),
                // Tables\Columns\TextColumn::make('revenue_tons')
                //     ->searchable(),
                // Tables\Columns\TextColumn::make('rate')
                //     ->searchable(),
                // Tables\Columns\TextColumn::make('prepaid')
                //     ->searchable(),
                // Tables\Columns\TextColumn::make('collect')
                //     ->searchable(),
                // Tables\Columns\TextColumn::make('ex_rate')
                //     ->searchable(),
                // Tables\Columns\TextColumn::make('prepaid2')
                //     ->searchable(),
                Tables\Columns\TextColumn::make('created_at')
                    ->dateTime()
                    ->sortable()
                    ->toggleable(isToggledHiddenByDefault: true),
                Tables\Columns\TextColumn::make('updated_at')
                    ->dateTime()
                    ->sortable()
                    ->toggleable(isToggledHiddenByDefault: true),
                Tables\Columns\TextColumn::make('deleted_at')
                    ->dateTime()
                    ->sortable()
                    ->toggleable(isToggledHiddenByDefault: true),
            ])
            ->filters([
                Tables\Filters\TrashedFilter::make(),
            ])
            ->actions([
                // Tables\Actions\EditAction::make(),
                Tables\Actions\ActionGroup::make([
                    Action::make('print')
                        // ->url(fn (Billoflading $record): string => route('filament.admin.resources.shipping.billofladings.print', $record))
                        ->url(fn (Billoflading $record): string => route('shipping.billofladings.print', $record))
                        ->icon('heroicon-o-printer')
                        ->openUrlInNewTab(),
                    Action::make('shipment-advice')
                        ->label('Send Shipment Advice')
                        // ->url(fn (Billoflading $record): string => route('filament.admin.resources.shipping.billofladings.print', $record))
                        ->url(fn (Billoflading $record): string => route('shipping.billofladings.shipment-advice', $record))
                        ->icon('heroicon-o-printer')
                        ->openUrlInNewTab(),
                    Tables\Actions\ViewAction::make()->icon('heroicon-o-eye'),
                    Tables\Actions\EditAction::make()->icon('heroicon-o-pencil-square'),
                    Tables\Actions\DeleteAction::make()->icon('heroicon-o-trash'),
                ]),
            ])
            ->bulkActions([
                Tables\Actions\BulkActionGroup::make([
                    Tables\Actions\DeleteBulkAction::make(),
                    Tables\Actions\ForceDeleteBulkAction::make(),
                    Tables\Actions\RestoreBulkAction::make(),
                ]),
            ])
            ->emptyStateActions([
                Tables\Actions\CreateAction::make(),
            ]);
    }
    
    public static function getRelations(): array
    {
        return [
            RelationManagers\TrackingRelationManager::class,
            // RelationManagers\BlChargesRelationManager::class,
        ];
    }
    
    public static function getPages(): array
    {
        return [
            'index' => Pages\ListBillofladings::route('/'),
            'create' => Pages\CreateBilloflading::route('/create'),
            'edit' => Pages\EditBilloflading::route('/{record}/edit'),
        ];
    }    
    
    public static function getEloquentQuery(): Builder
    {
        return parent::getEloquentQuery()
            ->withoutGlobalScopes([
                SoftDeletingScope::class,
            ]);
    }
}
