<?php

namespace App\Filament\Office\Resources;

use App\Models\BL;
use Filament\Forms;
use Filament\Tables;
use App\Enums\BLTypes;
use Filament\Forms\Form;
use App\Enums\CargoTypes;
use Filament\Tables\Table;
use App\Enums\LoadingTypes;
use App\Enums\ShipmentTypes;
use App\Enums\ContainerSizes;
use Filament\Resources\Resource;
use Filament\Forms\Components\Grid;
use Filament\Tables\Actions\Action;
use Filament\Tables\Filters\Filter;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\Toggle;
use Filament\Forms\Components\Section;
use Filament\Forms\Components\Repeater;
use Filament\Forms\Components\Textarea;
use Illuminate\Database\Eloquent\Model;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\DatePicker;
use Illuminate\Database\Eloquent\Builder;
use Filament\Tables\Enums\ActionsPosition;
use App\Filament\Office\Resources\BLResource\Pages;
use Illuminate\Database\Eloquent\SoftDeletingScope;
use App\Filament\Office\Resources\BLResource\RelationManagers;
use App\Filament\Office\Resources\CompanyResource\CompanyForms;
use Filament\Forms\Components\Radio;

class BLResource extends Resource
{
    protected static ?string $model = BL::class;

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

    protected static ?string $navigationGroup = 'Shipping';
    protected static ?string $navigationIcon = 'heroicon-o-ticket';
    protected static ?string $navigationLabel = 'Bill Of Ladings';
    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 (BL) number should be unique! Please collect BL number from our agent.')
                        ->required()
                        ->columnSpan(2),
                    DatePicker::make('etd')
                        ->label('Estimated time of departure')
                        ->required()
                        ->default('+1days'),
                    DatePicker::make('eta')
                        ->label('Estimated time of arrival')
                        ->required()
                        ->default('+7days'),
                ])->columns(2),
    
                // Vessel 
                Section::make('Vessel')
                ->description('Write voyage details')
                ->schema([
                    TextInput::make('pre_carriage_vessel')
                        ->label('Pre-carriage Vessel')
                        ->columnSpan(3),
                    TextInput::make('voy_no_pre_carriage')
                        ->label('Voyage No (Pre-carriage)')
                        ->columnSpan(3),
                    TextInput::make('ocean_vessel')
                        ->required()
                        ->label('Ocean Vessel')
                        ->columnSpan(3),
                    TextInput::make('voy_no_destination')
                        ->required()
                        ->label('Voyage No (Destination)')
                        ->columnSpan(3),

                    // Discharge / Destination
                    Select::make('place_of_loading_id')
                        ->label('Place of Loading (POL)')
                        ->relationship('port_of_discharge', 'name')
                        ->searchable(['name', 'iso', 'country_port_iso', 'country_name'])
                        ->getOptionLabelFromRecordUsing(fn (Model $record) => "{$record->name} ({$record->iso}), {$record->country_name}")
                        ->required()
                        ->columnSpan(3),
                    Select::make('port_of_discharge_id')
                        ->required()
                        ->label('Port of Discharge (POD)')
                        ->relationship('port_of_discharge', 'name')
                        ->searchable(['name', 'iso', 'country_port_iso', 'country_name'])
                        ->getOptionLabelFromRecordUsing(fn (Model $record) => "{$record->name} ({$record->iso}), {$record->country_name}")
                        ->reactive()
                        ->columnSpan(3),
                    TextInput::make('place_of_receipt')
                        ->required()
                        ->label('Place of Receipt (POR)')
                        ->required()
                        ->columnSpan(6),
                ])->columns(6),

                // Container Info 
                Section::make('Destination')
                ->description('We will connect our agent based on your destination info')
                ->schema([
                    TextInput::make('final_destination')
                        ->label('Final Destination Name')
                        ->required()
                        ->columnSpan(2),
                    Select::make('final_destination_country_id')
                        ->label('Final Destination Country')
                        // ->relationship('final_destination_country', 'name')
                        ->options(\App\Models\Country::all()->pluck('name', 'id'))
                        ->reactive()
                        ->afterStateUpdated(function (callable $set) {
                            $set('final_destination_city_id', '');
                        })
                        ->searchable(['name', 'iso3', 'iso2', 'numeric_code', 'capital', 'currency'])
                        ->required()
                        ->exists(table: \App\Models\Office::class, column: 'country_id')
                        ->validationMessages([
                            'exists' => 'Sorry! We don\'t have any office there.',
                        ]),
                    Select::make('final_destination_city_id')
                        ->label('Final Destination City')
                        // ->relationship('final_destination_city', 'name')
                        ->options(function(callable $get) {
                            $country = \App\Models\Country::find($get('final_destination_country_id'));
                            if ($country) {
                                return $country->cities->pluck('name', 'id');
                            }
                            return [''=>'Please Choose A Country'];
                        })
                        ->searchable(['name', 'country_code'])
                        ->required()
                        ->exists(table: \App\Models\Office::class, column: 'city_id')
                        ->validationMessages([
                            'exists' => 'Sorry! We don\'t have any office there.',
                        ]),
                ])->columns(2),

                // Container Info 
                Section::make('Container Info')
                // ->description('Description')
                ->schema([
                    TextInput::make('weight')
                        ->required(),
                    TextInput::make('net_weight')
                        ->required()
                        ->label('Net Weight'),
                    TextInput::make('measurement'),
                    TextInput::make('qty')
                        ->required()
                        ->label('No. Of Packages'),
                    // RichEditor::make('container_info')->columnSpan(4),
                    Textarea::make('discription_of_goods')
                        ->rows(5)
                        ->required()
                        ->maxLength(500)
                        ->columnSpan(4)
                        ->hint('Maximum 500 characters')
                        ->hintIcon('heroicon-o-information-circle'),
                    Textarea::make('marks')
                        ->rows(5)
                        ->maxLength(500)
                        ->columnSpan(4)
                        ->hint('Maximum 500 characters')
                        ->hintIcon('heroicon-o-information-circle'),
                    Textarea::make('rider_sheet')->label('Rider Sheet (If required)')
                        ->rows(5)
                        ->autosize()
                        ->columnSpan(4),
                ])->columns(4),

                Repeater::make('bl_containers')
                ->hint('Duplicate Container & Seal number are not allowed.')
                ->hintIcon('heroicon-o-information-circle')
                ->label('Containers')
                ->schema([
                    TextInput::make('container_num')
                        ->label('Container Number')
                        ->required()
                        ->distinct()
                        ->live()
                        ->helperText('Unique Number Only')
                        ->columnSpan(6),
                    TextInput::make('seal_no')
                        ->label('Seal number')
                        ->helperText('Unique Number Only')
                        ->distinct()
                        ->live()
                        ->required()
                        ->columnSpan(6),

                    Select::make('container_size')
                        ->options(ContainerSizes::class)
                        ->default('20_hc')
                        ->required()
                        ->searchable()
                        ->columnSpan(4),
                    TextInput::make('pack_qty')
                        ->label('Qty (pcs/pck)')
                        ->columnSpan(4),
                    TextInput::make('measurement')
                        ->label('Measurement')
                        ->columnSpan(4),

                    TextInput::make('gross_weight')
                        ->label('Gross Weight (KGs)')
                        ->columnSpan(4),
                    TextInput::make('net_weight')
                        ->label('Net Weight (KGs)')
                        ->columnSpan(4),
                    TextInput::make('vgm')
                        ->label('VGM (KGs)')
                        ->columnSpan(4),
                ])
                ->relationship()
                ->cloneable()
                ->collapsible()
                // ->orderable()
                ->minItems(1)
                ->columns(12)
                ->itemLabel(fn (array $state): ?string => $state['container_num'] ?? null)
                ->addActionLabel('Add More Container'),

                // Frieght Info
                Section::make('Frieght Info')
                // ->description('Description')
                ->schema([
                    Select::make('freight_type')
                        ->options([
                            'prepaid' => 'Prepaid', 
                            'postpaid' => 'Postpaid', 
                            'collect' => 'Collect'
                            ])
                        ->default('prepaid')
                        ->required()
                        ->columnSpan(3),
                    Textarea::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),
            ])
            ->columnSpan(['lg' => 2])
            ->disabled(fn (?Model $record): bool => !empty($record->locked)),

            Forms\Components\Group::make()
            ->schema([
                Section::make('Status')
                // ->description('Description')
                ->schema([
                    Grid::make([
                        'default' => 1,
                        'sm' => 2,
                    ])
                    ->schema([
                        Toggle::make('is_final')->label('Final'),
                        Toggle::make('locked'),
                    ]),
                    
                    // Select::make('shipment_type')
                    //     ->options(ShipmentTypes::class)
                    //     ->default('fcl')
                    //     ->required(),
                    Select::make('cargo_type')
                        ->options(CargoTypes::class)
                        ->default('lcl_lcl')
                        ->required(),
                    Select::make('loading_type')
                        ->options(LoadingTypes::class)
                        ->default('cy_cy')
                        ->required(),
                    // TextInput::make('editing_time'),
                    Select::make('editing_time')
                        ->label('Editing Time Allowed')
                        // ->live()
                        // ->reactive()
                        ->default(1*24*60*60)
                        ->helperText(fn(?Model $record):string|null => !empty($record)?'Created ' . $record->created_at->diffForHumans():null)
                        ->options([
                            1*24*60*60 => '1 Day',
                            2*24*60*60 => '2 Days',
                            3*24*60*60 => '3 Days',
                            4*24*60*60 => '4 Days',
                            5*24*60*60 => '5 Days',
                            6*24*60*60 => '6 Days',
                            7*24*60*60 => '7 Days',
                        ]),
                    Select::make('bl_type')
                        ->label('BL Type')
                        ->options(BLTypes::class)
                        ->default('draft')
                        ->required(),
                    Select::make('bl_status')
                        ->label('BL Status')
                        ->options(\App\Models\Status::all()->pluck('status', 'id'))
                        ->required()
                        ->default(1),
                    // TextInput::make('container_tues')
                    //     ->numeric()
                    //     ->default(1)
                    //     ->required(),
                ]),
                    
                // customer
                Section::make('Customer')
                // ->description('First line is considered as Company Name and other lines as Address')
                ->description('Write Name on first line and Address below of it!')
                ->schema([
                    // TextInput::make('shipper_name')
                    //     ->required(),
                    TextArea::make('shipper')
                        ->label('Shipper Name & Address')
                        ->required()
                        ->helperText(str('Hit **⏎ Enter** to add new line!')->inlineMarkdown()->toHtmlString()),
                    // TextInput::make('consignee_name')
                    //     ->required(),
                    TextArea::make('consignee')
                        ->label('Consignee Name & Address')
                        ->required()
                        ->helperText(str('Hit **⏎ Enter** to add new line!')->inlineMarkdown()->toHtmlString()),
                    // TextInput::make('notify_party_name')
                    //     ->label('1st Notify Party Name')
                    //     ->required(),
                    TextArea::make('notify_party')
                        ->label('1st Notify Party Name & Address')
                        ->required()
                        ->helperText(str('Hit **⏎ Enter** to add new line!')->inlineMarkdown()->toHtmlString()),
                    // TextInput::make('notify_party2_name')
                    //     ->label('2nd Notify Party Name'),
                    TextArea::make('notify_party2')
                        ->label('2nd Notify Party Name & Address')
                        ->helperText(str('Hit **⏎ Enter** to add new line!')->inlineMarkdown()->toHtmlString()),
                ])
                ->disabled(fn (?Model $record): bool => !empty($record->locked)),

                // Ref. 
                Section::make('Reference')
                // ->description('Description')
                ->schema([
                    TextInput::make('booking_ref_no')
                        ->label('Booking reference number'),
                    TextInput::make('shipper_ref')
                        ->label('Shipper reference number'),
                    Radio::make('original_bl')
                        ->label('Number of Original BL(s)')
                        ->options([
                            1 => "1 (One)", 
                            2 => "2 (Two)", 
                            3 => "3 (Three)"
                        ])
                        ->inline()
                        ->inlineLabel(false)
                        ->default(1)
                        ->required(),
                    DatePicker::make('shipped_on_board')
                        // ->required()
                        // ->default('+1days')
                        ->helperText(str('Leave empty if date is same as **ETA**!')->inlineMarkdown()->toHtmlString()),
                ])
                ->disabled(fn (?Model $record): bool => !empty($record->locked)),

                // Payment Info
                Section::make('Payment Info')
                // ->description('Description')
                ->schema([
                    Select::make('invoice_to_company_id')
                        ->label('Invoice To (Company)')
                        // ->options(\App\Models\Port::all()->pluck('name', 'id'))
                        ->relationship('invoice_to_company', 'name')
                        ->getOptionLabelFromRecordUsing(fn (Model $record) => "{$record->name} ({$record->code})")
                        ->searchable(['name', 'code', 'website', 'primary_email'])
                        ->reactive()
                        ->createOptionForm([
                            CompanyForms::getAddForm()
                        ]),
                    TextInput::make('payable_at')
                        ->required(),
                    TextInput::make('place_issue')
                        ->required()
                        ->label('Place Of Issue'),
                    DatePicker::make('issue_date')
                        ->helperText(str('Leave empty if date is same as **ETA**!')
                        // ->default(today())
                        ->inlineMarkdown()->toHtmlString()),
                ])
                ->disabled(fn (?Model $record): bool => !empty($record->locked)),
            ])
            ->columnSpan(['lg' => 1]),
        ])
        ->columns(3);
    }

    public static function table(Table $table): Table
    {
        return $table
            ->columns([
                Tables\Columns\TextColumn::make('bl_no')
                    ->label('BL Number')
                    ->description(fn (?Model $record): string => 'POL: '.$record->place_of_loading->name . ' (' . $record->place_of_loading->iso . ')' . ' - POD: ' . $record->port_of_discharge->name . ' (' . $record->port_of_discharge->iso . ')')
                    ->searchable()
                    ->sortable(),
                Tables\Columns\TextColumn::make('etd')
                    ->label('ETD')
                    ->formatStateUsing(fn (string $state): string => \Carbon\Carbon::parse($state)->toFormattedDateString())
                    ->description(fn (?Model $record): string => 'ETA: ' . \Carbon\Carbon::parse($record->eta)->toFormattedDateString())
                    ->searchable()
                    ->sortable(),
                Tables\Columns\TextColumn::make('booking_ref_no')
                    ->label('Booking No.')
                    ->sortable()
                    ->searchable()
                    ->toggleable(isToggledHiddenByDefault: true),
                Tables\Columns\TextColumn::make('ocean_vessel')
                    ->label('Ocean Vessel')
                    ->sortable()
                    ->searchable(isIndividual: true),
                Tables\Columns\TextColumn::make('voy_no_destination')
                    ->label('Voyage')
                    ->sortable()
                    ->searchable(isIndividual: true),
                Tables\Columns\TextColumn::make('pre_carriage_vessel')
                    ->label('Vessel')
                    ->description(fn (?Model $record): string => 'Voy: '.$record->voy_no_pre_carriage)
                    ->sortable()
                    ->toggleable(isToggledHiddenByDefault: true),
                Tables\Columns\TextColumn::make('final_destination')
                    ->label('Final Destination')
                    ->description(fn (?Model $record): string => $record->final_destination_city->name.' ⋅ '.$record->final_destination_country->name)
                    ->sortable(),
                Tables\Columns\TextColumn::make('issue_date')
                    ->label('Issued')
                    ->formatStateUsing(fn (string $state): string => \Carbon\Carbon::parse($state)->diffForHumans())
                    ->description(fn (?Model $record): string => $record->place_issue)
                    ->sortable(),
                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),
            ])
            ->defaultSort('created_at', 'desc')
            // ->recordClasses(function(Model $record){
            //     $class_opacity = match ($record->locked) {
            //         1 => 'opacity-30',
            //         default => null,
            //     };
            //     $class_final = match ($record->is_final) {
            //         1 => 'border-s-2 border-agent-600 dark:border-agent-300',
            //         default => null,
            //     };
            //     // 'reviewing' => 'border-s-2 border-orange-600 dark:border-orange-300',
            //     // 'published' => 'border-s-2 border-green-600 dark:border-green-300',
            //     return $class_opacity .' '. $class_final;
            // })
            // ->striped()
            ->searchOnBlur()
            ->filters([
                Filter::make('etd')
                    ->form([
                        DatePicker::make('etd_from')
                            ->label('ETD From (date)'),
                        DatePicker::make('etd_until')
                            ->label('ETD Until (date)'),
                    ])
                    ->query(function (Builder $query, array $data): Builder {
                        return $query
                            ->when(
                                $data['etd_from'],
                                fn (Builder $query, $date): Builder => $query->whereDate('etd', '>=', $date),
                            )
                            ->when(
                                $data['etd_until'],
                                fn (Builder $query, $date): Builder => $query->whereDate('etd', '<=', $date),
                            );
                    }),
                
                // Filter::make('eta')
                //     ->form([
                //         DatePicker::make('eta_from')
                //             ->label('ETA From (date)'),
                //         DatePicker::make('eta_until')
                //             ->label('ETA Until (date)'),
                //     ])
                //     ->query(function (Builder $query, array $data): Builder {
                //         return $query
                //             ->when(
                //                 $data['eta_from'],
                //                 fn (Builder $query, $date): Builder => $query->whereDate('eta', '>=', $date),
                //             )
                //             ->when(
                //                 $data['eta_until'],
                //                 fn (Builder $query, $date): Builder => $query->whereDate('eta', '<=', $date),
                //             );
                //     }),
                Tables\Filters\SelectFilter::make('bl_type')
                    ->multiple()
                    ->options(BLTypes::class),
                Tables\Filters\SelectFilter::make('bl_status')
                    ->multiple()
                    ->options(fn (): array => \App\Models\Status::query()->pluck('status', 'id')->all()),
                Filter::make('is_final')
                    ->label('Only Final BLs')
                    ->toggle()
                    ->query(fn (Builder $query): Builder => $query->where('is_final', true)),
                Filter::make('locked')
                    ->label('Only Locked BLs')
                    ->toggle()
                    ->query(fn (Builder $query): Builder => $query->where('locked', true)),
                Tables\Filters\TrashedFilter::make(),
            ])
            ->deferFilters()
            ->actions([
                Tables\Actions\ActionGroup::make([
                    Action::make('print')
                        ->url(fn (?Model $record): string => route('shipping.bl.show', $record->bl))
                        ->icon('heroicon-o-printer')
                        ->openUrlInNewTab(),
                    
                    Action::make('pdf')
                        ->label('PDF')
                        ->url(fn (?Model $record): string => route('shipping.bl.pdf', $record->bl))
                        ->icon('heroicon-o-document')
                        // ->color('success')
                        ->openUrlInNewTab(),
                        
                    Tables\Actions\EditAction::make()->icon('heroicon-o-pencil-square'),
                    Tables\Actions\DeleteAction::make()->icon('heroicon-o-trash'),
                ]),
            ], position: ActionsPosition::BeforeColumns)
            ->bulkActions([
                Tables\Actions\BulkActionGroup::make([
                    Tables\Actions\DeleteBulkAction::make(),
                    Tables\Actions\ForceDeleteBulkAction::make(),
                    Tables\Actions\RestoreBulkAction::make(),
                ]),
            ]);
    }

    public static function getRelations(): array
    {
        return [
            //
        ];
    }

    public static function getPages(): array
    {
        return [
            'index' => Pages\ListBLS::route('/'),
            'create' => Pages\CreateBL::route('/create'),
            'edit' => Pages\EditBL::route('/{record}/edit'),
        ];
    }

    public static function getEloquentQuery(): Builder
    {
        return parent::getEloquentQuery()
            ->withoutGlobalScopes([
                SoftDeletingScope::class,
                'organization'
            ]);
    }
}
