<?php

declare(strict_types=1);

namespace App\Filament\Widgets\Supervisor;

use App\Models\Installment;
use App\Services\CollectorVisibilityResolver;
use Carbon\Carbon;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Table;
use Filament\Widgets\TableWidget as BaseWidget;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Auth;

/**
 * Tabla de cuotas que vencen hoy.
 *
 * Permite al supervisor ver qué clientes deben pagar hoy
 * y hacer seguimiento.
 */
class InstallmentsDueTodayTable extends BaseWidget
{
    protected static ?string $heading = 'Cuotas por Cobrar Hoy';

    protected static ?int $sort = 5;

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

    /**
     * Solo visible para Supervisores.
     */
    public static function canView(): bool
    {
        $user = Auth::user();

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

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

        // Visibilidad supervisor→cobrador (#71).
        $collectorIds = app(CollectorVisibilityResolver::class)->visibleCollectorIds($user);

        return $table
            ->query(
                Installment::query()
                    ->where('company_id', $companyId)
                    ->whereHas('credit', function (Builder $q) use ($collectorIds) {
                        $q->leafCredits()
                            ->whereIn('status', ['active', 'delayed', 'overdue']);
                        if ($collectorIds !== null) {
                            $q->whereIn('collector_user_id', $collectorIds);
                        }
                    })
                    ->where('due_date', $today->toDateString())
                    ->where('status', '!=', 'paid')
                    ->with(['credit.client', 'credit.collector'])
            )
            ->columns([
                TextColumn::make('credit.client.name')
                    ->label('Cliente')
                    ->searchable()
                    ->sortable()
                    ->limit(20),

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

                TextColumn::make('installment_number')
                    ->label('Cuota')
                    ->sortable()
                    ->formatStateUsing(fn (int $state, Installment $record): string => "#{$state} de {$record->credit->installments_count}"
                    ),

                // `principal_balance_after` NO es lo que el cliente paga hoy: es el saldo de
                // capital del credito DESPUES de esta cuota (columna de la tabla de
                // amortizacion). Mostrarla aqui inflaba el monto ~2,8x — a un cliente
                // que debia $68.200 le aparecia $540.000 — y, peor, ordenaba la lista
                // de cobro del dia por el tamano del credito en vez de por lo que hay
                // que recaudar. Lo correcto es `remaining_amount` (total - pagado).
                TextColumn::make('remaining_amount')
                    ->label('Monto a Cobrar')
                    ->money('COP')
                    ->sortable(query: fn (Builder $query, string $direction): Builder => $query->orderByRaw(
                        'GREATEST(0, total_amount - amount_paid) '.($direction === 'desc' ? 'desc' : 'asc')
                    ))
                    ->color('danger'),

                TextColumn::make('status')
                    ->label('Estado')
                    ->badge()
                    ->formatStateUsing(fn (string $state): string => match ($state) {
                        'pending' => 'Pendiente',
                        'partial' => 'Parcial',
                        'paid' => 'Pagado',
                        default => ucfirst($state),
                    })
                    ->color(fn (string $state): string => match ($state) {
                        'pending' => 'warning',
                        'partial' => 'info',
                        'paid' => 'success',
                        default => 'gray',
                    }),

                TextColumn::make('credit.status')
                    ->label('Estado Crédito')
                    ->badge()
                    ->formatStateUsing(fn (string $state): string => match ($state) {
                        'active' => 'Activo',
                        'delayed' => 'En mora',
                        'overdue' => 'Vencido',
                        default => ucfirst($state),
                    })
                    ->color(fn (string $state): string => match ($state) {
                        'active' => 'success',
                        'delayed' => 'warning',
                        'overdue' => 'danger',
                        default => 'gray',
                    }),
            ])
            ->defaultSort(fn (Builder $query): Builder => $query->orderByRaw('GREATEST(0, total_amount - amount_paid) DESC'))
            ->paginated([10, 25, 50])
            ->emptyStateHeading('Sin cuotas para hoy')
            ->emptyStateDescription('No hay cuotas programadas para cobrar hoy.')
            ->emptyStateIcon('heroicon-o-calendar');
    }
}
