<?php

declare(strict_types=1);

namespace App\Filament\Resources\Credits\Actions;

use App\Enums\CreditAuditEvent;
use App\Models\Credit;
use App\Services\CreditOperationService;
use App\Services\CreditStatusSyncService;
use Filament\Actions\Action;
use Filament\Notifications\Notification;
use Illuminate\Support\Facades\Gate;

/**
 * Devuelve el crédito a la cartera operativa.
 *
 * El estado al que vuelve NO se adivina ni se guarda de antes: se recalcula.
 * Mientras estuvo archivado el tiempo siguió corriendo y sus cuotas pudieron
 * vencer, así que un crédito que se archivó "al día" puede volver en mora. El
 * resolver mira las cuotas y decide.
 *
 * `SmartCreditStateResolver` trata `archived` como estado inmutable —para que
 * la reconciliación nocturna no lo saque solo—, así que hay que devolverlo
 * primero a un estado que sí acepte recálculo y luego forzar la sincronización.
 */
class UnarchiveCreditAction
{
    public static function make(): Action
    {
        return Action::make('unarchive_credit')
            ->label('Desarchivar crédito')
            ->icon('heroicon-o-archive-box-arrow-down')
            ->color('success')
            ->requiresConfirmation()
            ->modalIcon('heroicon-o-archive-box-arrow-down')
            ->modalHeading('Devolver el crédito a la cartera')
            ->modalDescription(
                'El cobrador volverá a verlo y su saldo regresa a la cartera. '.
                'El estado se recalcula según sus cuotas: si vencieron mientras estaba archivado, volverá en mora.'
            )
            ->modalSubmitActionLabel('Desarchivar')
            ->visible(fn (?Credit $record): bool => filled($record) && Gate::allows('unarchive', $record))
            ->action(function (Credit $credit): void {
                Gate::authorize('unarchive', $credit);

                // Paso obligado: `archived` es inmutable para el resolver, así que
                // sin esto `forceSync` lo dejaría archivado.
                $credit->update(['status' => Credit::STATUS_ACTIVE]);

                app(CreditStatusSyncService::class)->forceSync($credit);

                $credit->refresh();

                app(CreditOperationService::class)->audit(
                    creditId: $credit->id,
                    action: CreditAuditEvent::CREDIT_UNARCHIVED,
                    data: ['estado_resultante' => $credit->status],
                );

                Notification::make()
                    ->title('Crédito devuelto a la cartera')
                    ->success()
                    ->body('Quedó como "'.$credit->getStatusLabel().'" y el cobrador ya puede verlo.')
                    ->send();
            });
    }
}
