<?php
// app/Filament/Resources/PaymentResource.php

declare(strict_types=1);

namespace App\Filament\Resources;

use App\Filament\Resources\PaymentResource\Pages;
use App\Models\Payment;
use Filament\Forms;
use Filament\Forms\Form;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\Textarea;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\Toggle;
use Filament\Forms\Get;
use Filament\Forms\Set;
use Filament\Resources\Resource;
use Filament\Tables;
use Filament\Tables\Table;

class PaymentResource extends Resource
{
    protected static ?string $model = Payment::class;

    protected static ?string $navigationIcon   = 'heroicon-o-banknotes';
    protected static ?string $navigationGroup  = 'Payments';
    protected static ?string $navigationLabel  = 'Payments';
    protected static ?string $modelLabel       = 'Payment';
    protected static ?string $pluralModelLabel = 'Payments';
    protected static ?int    $navigationSort   = 1;

    /** Keep the toggle choice out of the DB but available to afterCreate */
    protected static bool $shouldCreateLink = true;

    /* =========================================================================
     | Lifecycle hooks
     * ========================================================================= */

    public static function mutateFormDataBeforeCreate(array $data): array
    {
        // Remember the toggle choice in a static property (not persisted)
        static::$shouldCreateLink = (bool) ($data['create_link_now'] ?? true);

        // Ensure the transient toggle is NOT written to the DB
        unset($data['create_link_now']);

        return $data;
    }

    public static function afterCreate(Payment $record, array $data): void
    {
        if (! static::$shouldCreateLink) {
            return;
        }

        // Requires: Payment model has relation ->link()
        // public function link(){ return $this->hasOne(\App\Models\PaymentLink::class); }
        $record->loadMissing('link');

        if (blank(optional($record->link)->public_token)) {
            $record->link()->create([
                'tenant_id'    => $record->tenant_id,
                'public_token' => bin2hex(random_bytes(24)), // or Str::random(48)
                // 'expires_at' => now()->addDays(30),
            ]);

            $record->unsetRelation('link');
            $record->load('link');
        }
    }

    /* =========================================================================
     | Form (UI shows dollars; DB stores cents)
     * ========================================================================= */
    public static function form(Form $form): Form
    {
        return $form->schema([
            // Associate to a Job (search by external_reference / reference / id)
            Select::make('job_id')
                ->label('Job reference')
                ->required()
                ->relationship(name: 'job', titleAttribute: 'external_reference')
                ->searchable()
                ->getOptionLabelUsing(function ($value) {
                    if (!$value) return null;
                    $j = \App\Models\Job::query()
                        ->select('id', 'external_reference', 'reference')
                        ->find($value);
                    if (!$j) return 'Unknown job';
                    return (string) ($j->external_reference ?: $j->reference ?: ('Job #'.$j->id));
                })
                ->getSearchResultsUsing(function (string $search) {
                    $q = \App\Models\Job::query()
                        ->select('id', 'external_reference', 'reference');

                    if ($search !== '') {
                        $q->where(function ($qq) use ($search) {
                            $qq->where('external_reference', 'like', "%{$search}%")
                               ->orWhere('reference', 'like', "%{$search}%");
                        });
                    }
                    if (ctype_digit($search)) {
                        $q->orWhere('id', (int) $search);
                    }

                    return $q->orderByDesc('id')->limit(50)->get()
                        ->mapWithKeys(fn ($j) => [
                            $j->id => (string) ($j->external_reference ?: $j->reference ?: ('Job #'.$j->id)),
                        ])->all();
                })
                ->preload()
                ->options(function () {
                    return \App\Models\Job::query()
                        ->select('id', 'external_reference', 'reference')
                        ->orderByDesc('id')->limit(20)->get()
                        ->mapWithKeys(fn ($j) => [
                            $j->id => (string) ($j->external_reference ?: $j->reference ?: ('Job #'.$j->id)),
                        ])->all();
                }),

            Select::make('type')
                ->label('Payment kind')
                ->required()
                ->options([
                    'deposit'       => 'Deposit',
                    'bond_hold'     => 'Bond Hold',
                    'one_off'       => 'One Off Payment',
                    'final_payment' => 'Final Payment',
                    'other'         => 'Other',
                ])
                ->default('bond_hold')
                ->helperText('Deposit reduces reservation total. Bond Hold is the authorization from the flow. Others are ad-hoc charges.'),


// ✅ NEW: Payment Status (works for Create & Edit)
Select::make('status')
    ->label('Payment status')
    ->options([
        'pending'          => 'Pending',
        'succeeded'        => 'Already paid',
        'failed'           => 'Failed',
        'requires_capture' => 'Requires capture',
        'authorized'       => 'Authorized',
        'canceled'         => 'Canceled',
    ])
    ->default('pending')
    ->required()
    ->helperText('Use “Already paid” if this was taken outside this system and you just need it recorded.'),



            // UI shows dollars; DB persists cents
            TextInput::make('amount_cents')
                ->label('Amount (NZD)')
                ->numeric()
                ->required()
                ->rule('gte:0.01') // validate in dollars
                // when loading the form: cents -> dollars
                ->formatStateUsing(fn ($state) =>
                    $state !== null
                        ? number_format(((int) $state) / 100, 2, '.', '')
                        : null
                )
                // when saving: dollars -> cents
                ->dehydrateStateUsing(fn ($state) =>
                    $state !== null && $state !== ''
                        ? (int) round(((float) $state) * 100)
                        : null
                )
                ->extraInputAttributes(['inputmode' => 'decimal', 'step' => '0.01'])
                ->reactive(),

            Textarea::make('purpose')
                ->label('Reason / memo')
                ->rows(2)
                ->placeholder('Optional note: e.g., add-on, parking ticket, etc.'),

            // Toggle that DOES NOT dehydrate to the DB
            Toggle::make('create_link_now')
    ->label('Create shareable pay link')
    ->default(true)
    ->helperText('Generates /pay/{token} after saving, so you can send to the customer.')
    ->dehydrated(false)
    ->live()
    ->disabled(fn (Get $get) => $get('status') === 'succeeded')   // ⬅️ add this line
    ->afterStateUpdated(fn (Set $set, $state) => static::$shouldCreateLink = (bool) $state),
        ]);
    }

    /* =========================================================================
     | Table
     * ========================================================================= */
    public static function table(Table $table): Table
    {
        return $table
            ->columns([
                Tables\Columns\TextColumn::make('job.external_reference')
                    ->label('Job Reference')
                    ->sortable()
                    ->searchable(),

                Tables\Columns\BadgeColumn::make('type')
                    ->label('Type')
                    ->colors(['primary'])
                    ->sortable(),

                Tables\Columns\TextColumn::make('amount_cents')
                    ->label('Amount')
                    ->sortable()
                    ->formatStateUsing(fn ($state): string =>
                        'NZ$ ' . number_format(((int) ($state ?? 0)) / 100, 2)
                    ),

                Tables\Columns\BadgeColumn::make('status')
                    ->label('Status')
                    ->colors([
                        'success' => 'succeeded',
                        'warning' => 'pending',
                        'danger'  => 'failed',
                        'info'    => 'requires_capture',
                        'gray'    => 'canceled',
                        'primary' => 'authorized',
                    ])
                    ->sortable(),

                Tables\Columns\TextColumn::make('created_at')
                    ->label('Created')
                    ->dateTime()
                    ->sortable(),

                // Quick copy/open link from related PaymentLink
                Tables\Columns\TextColumn::make('link.public_token')
                    ->label('Pay link')
                    ->formatStateUsing(fn ($token): string => $token ? url('/pay/'.$token) : '—')
                    ->copyable()
                    ->copyMessage('Pay link copied')
                    ->copyMessageDuration(1500)
                    ->toggleable(isToggledHiddenByDefault: true),
            ])
            ->filters([
                Tables\Filters\SelectFilter::make('type')->options([
                    'deposit'       => 'Deposit',
                    'bond_hold'     => 'Bond Hold',
                    'one_off'       => 'One Off',
                    'final_payment' => 'Final Payment',
                    'other'         => 'Other',
                ]),
                Tables\Filters\SelectFilter::make('status')->options([
                    'pending'          => 'Pending',
                    'succeeded'        => 'Succeeded',
                    'failed'           => 'Failed',
                    'requires_capture' => 'Requires capture',
                    'authorized'       => 'Authorized',
                    'canceled'         => 'Canceled',
                ]),
            ])
            ->actions([
                Tables\Actions\ViewAction::make(),
                Tables\Actions\EditAction::make(),

                Tables\Actions\Action::make('openPayPage')
                    ->label('Open pay page')
                    ->icon('heroicon-o-link')
                    ->url(fn (Payment $record) => $record->link ? url('/pay/'.$record->link->public_token) : null)
                    ->openUrlInNewTab()
                    ->visible(fn (Payment $record) => filled($record->link?->public_token)),

                Tables\Actions\DeleteAction::make(),
            ])
            ->bulkActions([
                Tables\Actions\BulkActionGroup::make([
                    Tables\Actions\DeleteBulkAction::make(),
                ]),
            ])
            ->defaultSort('id', 'desc');
    }

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

    public static function getPages(): array
    {
        return [
            'index'  => Pages\ListPayments::route('/'),
            'create' => Pages\CreatePayment::route('/create'),
            'view'   => Pages\ViewPayment::route('/{record}'),
            'edit'   => Pages\EditPayment::route('/{record}/edit'),
        ];
    }
}
