<?php

namespace App\Filament\Admin\Resources;

use App\Enums\IconEnum;
use App\Enums\InvoiceStatus;
use App\Filament\Admin\Resources\CustomerResource\RelationManagers\InvoicesRelationManager;
use App\Filament\Admin\Resources\InvoiceResource\RelationManagers\OrdersRelationManager;
use App\Filament\Admin\Resources\InvoiceResource\RelationManagers\ProductServicesRelationManager;
use App\Models\Customer;
use App\Models\Invoice;
use Filament\Forms\Components\DatePicker;
use Filament\Forms\Components\Grid;
use Filament\Forms\Components\Group;
use Filament\Forms\Components\Placeholder;
use Filament\Forms\Components\Section;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\Split;
use Filament\Forms\Components\ToggleButtons;
use Filament\Forms\Form;
use Filament\Notifications\Notification;
use Filament\Resources\Resource;
use Filament\Support\Enums\FontWeight;
use Filament\Tables;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Collection;

class InvoiceResource extends Resource
{
    protected static ?string $model = Invoice::class;

    protected static ?string $navigationIcon = IconEnum::INVOICE->value;

    protected static ?string $navigationGroup = 'Financial';

    protected static ?int $navigationSort = 1;

    public static function form(Form $form): Form
    {
        return $form
            ->schema([
                Group::make()
                    ->schema([
                        Section::make([
                            Select::make('customer_id')
                                ->required()
                                ->label('Customer')
                                ->options(Customer::all()->pluck('company_name', 'id'))
                                ->reactive()
                                ->searchable()
                                ->disabledOn('edit')
                                ->columnSpan(2),

                            Split::make([
                                DatePicker::make('date')
                                    ->required()
                                    ->default(today()),
                                DatePicker::make('due_date'),
                            ])
                                ->columnSpan(2),

                            Grid::make(3)
                                ->schema([
                                    ToggleButtons::make('has_gst')
                                        ->label('GST')
                                        ->boolean('On', 'Off')
                                        ->default(true)
//                                        ->inline()
                                        ->colors([
                                            'true'  => 'info',
                                            'false' => 'info',
                                        ]),

                                    ToggleButtons::make('has_pst')
                                        ->label('PST')
                                        ->boolean('On', 'Off')
                                        ->default(false)
//                                        ->inline()
                                        ->colors([
                                            'true'  => 'info',
                                            'false' => 'info',
                                        ]),

                                    ToggleButtons::make('has_hst')
                                        ->label('HST')
                                        ->boolean('On', 'Off')
                                        ->default(false)
//                                        ->inline()
                                        ->colors([
                                            'true'  => 'info',
                                            'false' => 'info',
                                        ]),
                                ])->columnSpan(1),

                            ToggleButtons::make('status')
                                ->options(InvoiceStatus::class)
                                ->required()
                                ->inline()
                                ->default(InvoiceStatus::UNPAID)
                                ->columnSpan(1),

                        ])
                            ->columns(2)
                            ->columnSpan(2),

                        Section::make()
                            ->schema([
                                Placeholder::make('Id')
                                    ->label('ID')
                                    ->content(fn (Invoice $record): ?string => $record->internal_id),

                                Placeholder::make('Amounts')
                                    ->content(fn (Invoice $record): ?string => 'Total: $'.number_format($record->total, 2).', balance: $'.number_format($record->remainingBalance(), 2)),

                                Placeholder::make('Tax Rates when created')
                                    ->content(fn (Invoice $record): ?string => $record->gst_rate.'% GST, '.$record->pst_rate.'% PST, '.$record->hst_rate.'% HST'),

                                Placeholder::make('created_at')
                                    ->label('Timestamps')
                                    ->content(fn (Invoice $record): ?string => 'Created at '.$record->created_at->format('Y-m-d').', updated at '.$record->updated_at->format('Y-m-d')),

                            ])
                            ->columnSpan(1)
                            ->hidden(fn (?Invoice $record) => $record === null)
                            ->extraAttributes(['class' => 'h-full']),

                    ])
                    ->columns(3)
                    ->columnSpan(2),

            ])->columns(2);
    }

    public static function table(Table $table): Table
    {
        return $table
            ->columns([
                TextColumn::make('internal_id')
                    ->extraHeaderAttributes(fn ($livewire) => $livewire::class === InvoicesRelationManager::class ? ['class' => 'w-full'] : [false])
                    ->label('ID')
                    ->fontFamily('mono')
                    ->color('primary')
                    ->sortable()
                    ->searchable(query: function (Builder $query, $search) {
                        return $query->where('internal_id', 'like', "%{$search}%")
                            ->orWhereHas('orders', function (Builder $query) use ($search) {
                                return $query->where('customer_po', 'like', "%{$search}%")
                                    ->orWhere('internal_po', 'like', "%{$search}%");
                            });
                    }),

                TextColumn::make('customer.company_name')
                    ->hidden(fn ($livewire) => $livewire::class === InvoicesRelationManager::class)
                    ->sortable()
                    ->extraHeaderAttributes(['class' => 'w-full'])
                    ->searchable(),

                TextColumn::make('created_at')
                    ->label('Created')
                    ->date('Y-m-d')
                    ->searchable()
                    ->sortable(),

                TextColumn::make('subtotal')
                    ->money()
                    ->alignRight()
                    ->sortable()
                    ->searchable(),

                // FIXME: sortable doesn't sort correctly
                TextColumn::make('gst_amount')
                    ->label('GST/HST')
                    ->money()
                    ->getStateUsing(function (Invoice $record) {
                        return $record->has_gst
                            ? '$'.number_format($record->gst_amount, 2)
                            : ($record->has_hst ? '$'.number_format($record->hst_amount, 2) : '-');
                    })
                    ->alignRight()
                    ->searchable(query: function (Builder $query, string $search) {
                        $query->where(function ($query) use ($search) {
                            $query->where('hst_amount', 'like', "%{$search}%")
                                ->orWhere('gst_amount', 'like', "%{$search}%");
                        });
                    }),
                //                    ->sortable(query: function (Builder $query, string $direction) {
                //                        $query->orderByRaw("COALESCE(hst_amount, gst_amount, 0) $direction");
                //                    }),

                TextColumn::make('pst_amount')
                    ->label('PST')
                    ->getStateUsing(function (Invoice $record) {
                        return $record->has_pst ? '$'.number_format($record->pst_amount, 2) : '-';
                    })
                    ->alignRight()
                    ->sortable()
                    ->searchable(),

                TextColumn::make('total')
                    ->money()
                    ->alignRight()
                    ->weight(FontWeight::Medium)
                    ->sortable()
                    ->searchable(),

                TextColumn::make('balance')
                    ->getStateUsing(fn (Invoice $record) => $record->remainingBalance())
                    ->money()
                    ->alignRight()
                    ->weight(FontWeight::Bold),

                TextColumn::make('status')
                    ->badge(InvoiceStatus::class)
                    ->sortable(),
            ])

            ->filters([
                Tables\Filters\Filter::make('created_at')
                    ->form([
                        DatePicker::make('created_from')
                            ->label('From date'),
                        DatePicker::make('created_until')
                            ->label('Until date'),
                    ])
                    ->query(function (Builder $query, array $data): Builder {
                        return $query
                            ->when(
                                $data['created_from'],
                                fn (Builder $query, $date): Builder => $query->whereDate('date', '>=', $date),
                            )
                            ->when(
                                $data['created_until'],
                                fn (Builder $query, $date): Builder => $query->whereDate('date', '<=', $date),
                            );
                    }),

                Tables\Filters\SelectFilter::make('status')
                    ->options(InvoiceStatus::class),

            ], )

            ->groups([
                'status',
            ])

            ->defaultSort('id', 'desc')

            ->actions([
                Tables\Actions\EditAction::make()
                    ->hidden(fn ($livewire) => $livewire::class === InvoicesRelationManager::class),
            ])

            ->bulkActions([
                Tables\Actions\BulkAction::make('Mark as paid')
                    ->action(function (Collection $records) {
                        $records->each->setStatus(InvoiceStatus::PAID);
                        Notification::make()
                            ->title(count($records).' item(s) saved successfully')
                            ->success()
                            ->send();
                    })
                    ->icon('lucide-circle-check')
                    ->deselectRecordsAfterCompletion(),

                Tables\Actions\BulkActionGroup::make([
                    Tables\Actions\BulkAction::make('Mark as unpaid')
                        ->action(function (Collection $records) {
                            $records->each->setStatus(InvoiceStatus::UNPAID);
                            Notification::make()
                                ->title(count($records).' item(s) saved successfully')
                                ->success()
                                ->send();
                        })
                        ->icon('lucide-circle-x')
                        ->deselectRecordsAfterCompletion(),
                    Tables\Actions\DeleteBulkAction::make(),
                ])
                    ->label('Other actions'),
            ])
            ->selectCurrentPageOnly();
    }

    public static function canAccess(): bool
    {
        return auth()->user()->is_admin ?? false;
    }

    public static function getRelations(): array
    {
        return [
            OrdersRelationManager::class,
            ProductServicesRelationManager::class,
        ];
    }

    public static function getPages(): array
    {
        return [
            'index'  => \App\Filament\Admin\Resources\InvoiceResource\Pages\ListInvoices::route('/'),
            'create' => \App\Filament\Admin\Resources\InvoiceResource\Pages\CreateInvoice::route('/create'),
            'edit'   => \App\Filament\Admin\Resources\InvoiceResource\Pages\EditInvoice::route('/{record}/edit'),
        ];
    }
}
