<?php

declare(strict_types=1);

namespace App\Filament\Widgets\Admin;

use App\Filament\Resources\Credits\CreditResource;
use App\Filament\Resources\Payments\PaymentResource;
use App\Models\Credit;
use App\Models\User;
use App\Services\Metrics\DelinquencyMetricsService;
use Filament\Actions\Action;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Filters\SelectFilter;
use Filament\Tables\Table;
use Filament\Widgets\TableWidget as BaseWidget;
use Illuminate\Support\Facades\Auth;

/**
 * Tabla unificada de cartera en riesgo para el admin.
 *
 * Reemplaza TopOverdueCreditsTable con una vista completa paginada,
 * filtros por collector/estado, clasificación PAR y acciones directas.
 */
class OverduePortfolioTable extends BaseWidget
{
    protected static ?string $heading = 'Cartera en Riesgo';

    protected static ?int $sort = 4;

    protected int|string|array $columnSpan = 'full';

    public static function canView(): bool
    {
        $user = Auth::user();

        return $user && $user->hasRole('admin') && ! $user->isSuperAdmin();
    }

    public function table(Table $table): Table
    {
        $user = Auth::user();
        $companyId = $user->company_id;

        $service = app(DelinquencyMetricsService::class);
        $overdueData = $service->getAllOverdueCredits($companyId);
        $creditIds = $overdueData->pluck('credit_id')->toArray();

        return $table
            ->query(
                Credit::query()
                    ->whereIn('id', $creditIds ?: [0])
                    ->with(['client:id,name', 'collector:id,name'])
                    ->orderByRaw(
                        $creditIds
                            ? 'FIELD(id, '.implode(',', $creditIds).')'
                            : 'id'
                    )
            )
            ->columns([
                TextColumn::make('client.name')
                    ->label('Cliente')
                    ->searchable()
                    ->url(fn (Credit $record): string => route('filament.admin.resources.clients.view', $record->client_id)
                    )
                    ->limit(30),

                TextColumn::make('collector.name')
                    ->label('Collector')
                    ->badge()
                    ->color('gray')
                    ->default('Sin asignar'),

                // Clasificación PAR (Portfolio at Risk)
                TextColumn::make('par_bucket')
                    ->label('PAR')
                    ->getStateUsing(function (Credit $record) use ($overdueData): string {
                        return $overdueData->firstWhere('credit_id', $record->id)['par_bucket'] ?? 'PAR 1-30';
                    })
                    ->badge()
                    ->color(fn (string $state): string => match ($state) {
                        'PAR 90+' => 'danger',
                        'PAR 61-90' => 'danger',
                        'PAR 31-60' => 'warning',
                        default => 'info',
                    }),

                TextColumn::make('days_overdue')
                    ->label('Días Mora')
                    ->getStateUsing(fn (Credit $record): int => (int) ($overdueData->firstWhere('credit_id', $record->id)['max_days_overdue'] ?? 0)
                    )
                    ->badge()
                    ->color(fn (int $state): string => match (true) {
                        $state > 60 => 'danger',
                        $state > 30 => 'warning',
                        default => 'info',
                    }),

                TextColumn::make('overdue_balance')
                    ->label('Saldo Vencido')
                    ->getStateUsing(fn (Credit $record): float => $overdueData->firstWhere('credit_id', $record->id)['overdue_balance'] ?? 0
                    )
                    ->money('COP')
                    ->color('danger')
                    ->alignEnd(),

                TextColumn::make('total_balance')
                    ->label('Saldo Total')
                    ->getStateUsing(fn (Credit $record): float => $overdueData->firstWhere('credit_id', $record->id)['total_balance'] ?? 0
                    )
                    ->money('COP')
                    ->alignEnd(),

                // Qué porcentaje del saldo total ya está vencido
                TextColumn::make('overdue_pct')
                    ->label('% Vencido')
                    ->getStateUsing(function (Credit $record) use ($overdueData): string {
                        $data = $overdueData->firstWhere('credit_id', $record->id);
                        $total = $data['total_balance'] ?? 0;
                        $overdue = $data['overdue_balance'] ?? 0;
                        if ($total <= 0) {
                            return '—';
                        }

                        return number_format(($overdue / $total) * 100, 1).'%';
                    })
                    ->badge()
                    ->color(fn (string $state): string => match (true) {
                        $state === '—' => 'gray',
                        (float) rtrim($state, '%') >= 80 => 'danger',
                        (float) rtrim($state, '%') >= 50 => 'warning',
                        default => 'info',
                    }),

                TextColumn::make('last_payment')
                    ->label('Último Pago')
                    ->getStateUsing(fn (Credit $record): ?string => $overdueData->firstWhere('credit_id', $record->id)['last_payment_date'] ?? null
                    )
                    ->date('d/m/Y')
                    ->placeholder('Sin pagos'),

                TextColumn::make('status')
                    ->label('Estado')
                    ->badge()
                    ->formatStateUsing(fn (string $state): string => match ($state) {
                        'overdue' => 'Vencido',
                        'delayed' => 'En mora',
                        default => ucfirst($state),
                    })
                    ->color(fn (string $state): string => match ($state) {
                        'overdue' => 'danger',
                        'delayed' => 'warning',
                        default => 'gray',
                    }),
            ])
            ->filters([
                SelectFilter::make('collector_user_id')
                    ->label('Collector')
                    ->options(
                        User::where('company_id', $companyId)
                            ->whereHas('roles', fn ($q) => $q->where('name', 'collector'))
                            ->orderBy('name')
                            ->pluck('name', 'id')
                            ->toArray()
                    )
                    ->placeholder('Todos los collectors'),

                SelectFilter::make('status')
                    ->label('Estado')
                    ->options([
                        'delayed' => 'En mora',
                        'overdue' => 'Vencido',
                    ])
                    ->placeholder('Todos'),
            ])
            ->actions([
                Action::make('ver')
                    ->label('Ver')
                    ->icon('heroicon-o-eye')
                    ->color('gray')
                    ->url(fn (Credit $record): string => CreditResource::getUrl('view', ['record' => $record->id])
                    ),

                Action::make('pagar')
                    ->label('Registrar Pago')
                    ->icon('heroicon-o-banknotes')
                    ->color('success')
                    ->url(fn (Credit $record): string => PaymentResource::getUrl('create', ['credit_id' => $record->id])
                    ),
            ])
            ->defaultPaginationPageOption(10)
            ->paginated([10, 25, 50])
            ->emptyStateHeading('Sin créditos en mora')
            ->emptyStateDescription('Todos los créditos están al día.')
            ->emptyStateIcon('heroicon-o-check-circle');
    }
}
