<?php

namespace App\Filament\Widgets;

use App\Enums\Currency;
use App\Enums\PaymentStatus;
use App\Filament\Resources\SaleResource;
use App\Models\Account;
use App\Models\Payment;
use App\Models\Sale;
use App\Models\SystemSetting;
use Filament\Forms;
use Filament\Forms\Get;
use Filament\Notifications\Notification;
use Filament\Tables;
use Filament\Tables\Table;
use Filament\Widgets\TableWidget as BaseWidget;

class WeeklyCollectionsWidget extends BaseWidget
{
    protected static ?int $sort = 4;
    protected int | string | array $columnSpan = 'full';

    protected function getHeading(): string
    {
        $rate  = SystemSetting::current()->exchange_rate_usd_bob;
        $sales = Sale::query()
            ->whereBetween('expected_collect_date', [now()->startOfWeek()->toDateString(), now()->endOfWeek()->toDateString()])
            ->where('payment_status', '!=', PaymentStatus::Paid->value)
            ->get();

        $totalBob = $sales->sum(function (Sale $s) use ($rate) {
            $bal = $s->balance;
            return $s->currency === Currency::BOB ? $bal : round($bal * $rate, 2);
        });

        return '📅 Cobros esta semana — Total Bs. ' . number_format($totalBob, 2);
    }

    public function table(Table $table): Table
    {
        $rate = SystemSetting::current()->exchange_rate_usd_bob;

        return $table
            ->query(
                Sale::query()
                    ->whereBetween('expected_collect_date', [
                        now()->startOfWeek()->toDateString(),
                        now()->endOfWeek()->toDateString(),
                    ])
                    ->where('payment_status', '!=', PaymentStatus::Paid->value)
                    ->orderBy('expected_collect_date')
            )
            ->columns([
                Tables\Columns\TextColumn::make('expected_collect_date')
                    ->label('F. Cobro')
                    ->date('d/m/Y')
                    ->sortable(),

                Tables\Columns\TextColumn::make('client.name')
                    ->label('Cliente')
                    ->searchable(),

                Tables\Columns\TextColumn::make('title')
                    ->label('Venta')
                    ->limit(35),

                Tables\Columns\BadgeColumn::make('currency')
                    ->label('Mon.')
                    ->formatStateUsing(fn ($state) => $state instanceof Currency ? $state->value : $state)
                    ->colors(['success' => 'USD', 'warning' => 'BOB']),

                Tables\Columns\TextColumn::make('gross_amount')
                    ->label('Bruto')
                    ->getStateUsing(fn (Sale $r) => $r->currency->symbol() . number_format((float) $r->gross_amount, 2)),

                Tables\Columns\TextColumn::make('balance')
                    ->label('Saldo')
                    ->getStateUsing(fn (Sale $r) => $r->currency->symbol() . number_format($r->balance, 2))
                    ->color('danger'),

                Tables\Columns\TextColumn::make('equiv_bob')
                    ->label('Equiv. Bs.')
                    ->getStateUsing(function (Sale $r) use ($rate) {
                        $bal = $r->balance;
                        $bob = $r->currency === Currency::BOB ? $bal : round($bal * $rate, 2);
                        return 'Bs. ' . number_format($bob, 2);
                    })
                    ->color('warning')
                    ->weight('bold'),

                Tables\Columns\BadgeColumn::make('payment_status')
                    ->label('Estado')
                    ->formatStateUsing(fn ($state) => $state instanceof PaymentStatus ? $state->label() : $state)
                    ->colors(['danger' => 'unpaid', 'warning' => 'partial']),
            ])
            ->actions([
                Tables\Actions\Action::make('register_payment')
                    ->label('Pago')
                    ->icon('heroicon-o-banknotes')
                    ->color('success')
                    ->fillForm(fn (Sale $record): array => [
                        'amount'       => max(0, round($record->balance, 2)),
                        'currency'     => $record->currency->value,
                        'payment_date' => now()->toDateString(),
                        'account_id'   => Account::whereRaw('LOWER(name) LIKE ?', [
                            $record->currency === Currency::USD ? '%payoneer%' : '%nuna%'
                        ])->first()?->id ?? Account::first()?->id,
                        'note' => '',
                    ])
                    ->form(fn (Sale $record) => [
                        Forms\Components\Placeholder::make('sale_info')
                            ->label('Venta')
                            ->content("{$record->client?->name} — {$record->title}"),

                        Forms\Components\Placeholder::make('balance_info')
                            ->label('Saldo pendiente')
                            ->content($record->currency->symbol() . number_format($record->balance, 2)
                                . ($record->balance < $record->net_expected
                                    ? '  (parcial previo: ' . $record->currency->symbol() . number_format((float)$record->collected_amount_cached, 2) . ')'
                                    : '')),

                        Forms\Components\Grid::make(2)->schema([
                            Forms\Components\TextInput::make('amount')
                                ->label('Monto cobrado')
                                ->numeric()
                                ->required()
                                ->step(0.01)
                                ->minValue(0.01)
                                ->prefix(fn (Get $get) => match($get('currency')) { 'BOB' => 'Bs.', default => '$' }),

                            Forms\Components\Select::make('currency')
                                ->label('Moneda')
                                ->options(collect(Currency::cases())->mapWithKeys(fn ($e) => [$e->value => $e->label()]))
                                ->required(),

                            Forms\Components\DatePicker::make('payment_date')
                                ->label('Fecha de pago')
                                ->required()
                                ->default(now()),

                            Forms\Components\Select::make('account_id')
                                ->label('Cuenta destino')
                                ->options(Account::pluck('name', 'id'))
                                ->required()
                                ->searchable(),
                        ]),

                        Forms\Components\TextInput::make('note')
                            ->label('Nota (opcional)')
                            ->maxLength(255),
                    ])
                    ->action(function (Sale $record, array $data): void {
                        Payment::create([
                            'sale_id'            => $record->id,
                            'account_id'         => $data['account_id'],
                            'created_by_user_id' => auth()->id(),
                            'payment_date'       => $data['payment_date'],
                            'amount'             => $data['amount'],
                            'currency'           => Currency::from($data['currency']),
                            'fee_amount'         => 0,
                            'net_amount'         => $data['amount'],
                            'note'               => $data['note'] ?? '',
                        ]);
                        Notification::make()
                            ->title('Pago registrado')
                            ->body("{$record->client?->name} — {$record->currency->symbol()}{$data['amount']}")
                            ->success()
                            ->send();
                    })
                    ->modalHeading(fn (Sale $record) => "Registrar pago — {$record->client?->name}")
                    ->modalSubmitActionLabel('Confirmar pago')
                    ->modalWidth('lg'),

                Tables\Actions\Action::make('ver')
                    ->label('Ver')
                    ->icon('heroicon-o-eye')
                    ->url(fn (Sale $r) => SaleResource::getUrl('view', ['record' => $r])),
            ])
            ->paginated([5, 10]);
    }
}
