<?php

declare(strict_types=1);

namespace App\Filament\Resources\Credits\Actions;

use App\DTOs\RefinanceCreditData;
use App\Enums\Periodicity;
use App\Exceptions\CreditOperationException;
use App\Filament\Resources\Credits\CreditResource;
use App\Models\Credit;
use App\Services\CreditManager;
use App\Services\Credits\CreditOperationOrchestrator;
use App\ValueObjects\Money;
use Carbon\Carbon;
use Filament\Actions\Action;
use Filament\Forms\Components\DatePicker;
use Filament\Forms\Components\Placeholder;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\Textarea;
use Filament\Forms\Components\TextInput;
use Filament\Notifications\Notification;
use Filament\Schemas\Components\Section;

/**
 * Acción de Filament para REFINANCIAR un crédito.
 *
 * Refinanciación: Nuevo crédito que incluye deuda anterior + capital adicional.
 * HAY DESEMBOLSO de efectivo (solo el capital adicional).
 *
 * NOTA: Como hay desembolso, la fecha de inicio típicamente es "hoy",
 * pero se permite flexibilidad para casos especiales.
 */
class RefinanceCreditAction
{
    public static function make(): Action
    {
        return Action::make('refinance_credit')
            ->label('Refinanciar')
            ->icon('heroicon-o-banknotes')
            ->color('warning')
            ->modalHeading('Refinanciar Crédito')
            ->modalDescription(fn (Credit $record): string => sprintf(
                'Crea un nuevo crédito sumando el saldo pendiente (%s) + capital adicional. Se DESEMBOLSA el capital adicional.',
                '$ '.number_format(app(CreditManager::class)->getRemainingBalance($record), 2, ',', '.')
            )
            )
            ->modalSubmitActionLabel('Refinanciar Crédito')
            ->modalWidth('lg')
            ->visible(fn (?Credit $record): bool => filled($record) && app(CreditOperationOrchestrator::class)->canRefinance($record)
            )
            ->schema(fn (Credit $record): array => [
                Section::make('Información del crédito actual')
                    ->schema([
                        Placeholder::make('current_balance')
                            ->label('Saldo pendiente')
                            ->content(fn () => '$ '.number_format(
                                app(CreditManager::class)->getRemainingBalance($record),
                                2, ',', '.'
                            )),
                        Placeholder::make('current_rate')
                            ->label('Tasa actual')
                            ->content(fn () => $record->interest_rate.'%'),
                        Placeholder::make('current_periodicity')
                            ->label('Periodicidad actual')
                            ->content(fn () => Periodicity::from($record->periodicity)->getLabel()),
                    ])
                    ->columns(3),

                Section::make('Capital Adicional')
                    ->description('El capital adicional es el dinero NUEVO que se entregará al cliente.')
                    ->schema([
                        TextInput::make('additional_capital')
                            ->label('Capital adicional a entregar')
                            ->numeric()
                            ->minValue(1)
                            ->prefix('$')
                            ->required()
                            ->live(onBlur: true)
                            ->helperText('Este monto se DESEMBOLSARÁ al cliente'),

                        Placeholder::make('new_total')
                            ->label('Nuevo monto total del crédito')
                            ->content(function ($get) use ($record) {
                                $balance = app(CreditManager::class)->getRemainingBalance($record);
                                $additional = (float) ($get('additional_capital') ?? 0);
                                $total = $balance + $additional;

                                return '$ '.number_format($total, 2, ',', '.');
                            }),
                    ])
                    ->columns(2),

                Section::make('Configuración del nuevo crédito')
                    ->schema([
                        TextInput::make('new_installments')
                            ->label('Número de nuevas cuotas')
                            ->numeric()
                            ->minValue(1)
                            ->maxValue(365)
                            ->default($record->installments_count)
                            ->required(),

                        TextInput::make('new_interest_rate')
                            ->label('Nueva tasa de interés (%)')
                            ->numeric()
                            ->minValue(0)
                            ->maxValue(100)
                            ->step(0.01)
                            ->default($record->interest_rate)
                            ->suffix('%')
                            ->helperText('Dejar igual o ajustar'),

                        Select::make('periodicity')
                            ->label('Periodicidad')
                            ->options(Periodicity::class)
                            ->default($record->periodicity),

                        DatePicker::make('start_date')
                            ->label('Fecha de inicio (desembolso)')
                            ->default(Carbon::today())
                            ->required()
                            ->helperText('Fecha en que se desembolsa el capital adicional'),

                        DatePicker::make('first_due_date_override')
                            ->label('Primera fecha de vencimiento (opcional)')
                            ->helperText('Dejar vacío para calcular automáticamente'),
                    ])
                    ->columns(2),

                Textarea::make('reason')
                    ->label('Motivo de la refinanciación')
                    ->placeholder('Ej: Cliente solicitó capital adicional para inversión en negocio...')
                    ->rows(2)
                    ->columnSpanFull(),
            ])
            ->action(function (array $data, Credit $record) {
                try {
                    $dto = new RefinanceCreditData(
                        creditId: $record->id,
                        newInstallmentsCount: (int) $data['new_installments'],
                        additionalCapital: Money::of((float) $data['additional_capital']),
                        newInterestRate: isset($data['new_interest_rate'])
                            ? (string) $data['new_interest_rate']
                            : null,
                        periodicity: isset($data['periodicity']) && $data['periodicity'] instanceof Periodicity
                            ? $data['periodicity']->value
                            : ($data['periodicity'] ?? null),
                        startDate: isset($data['start_date']) ? Carbon::parse($data['start_date']) : null,
                        firstDueDateOverride: isset($data['first_due_date_override'])
                            ? Carbon::parse($data['first_due_date_override'])
                            : null,
                        reason: $data['reason'] ?? null,
                    );

                    $result = app(CreditOperationOrchestrator::class)->refinance($dto);

                    Notification::make()
                        ->title('Crédito refinanciado exitosamente')
                        ->success()
                        ->body($result->getSummaryMessage())
                        ->persistent()
                        ->send();

                    return redirect()->to(
                        CreditResource::getUrl('view', ['record' => $result->newCredit])
                    );
                } catch (CreditOperationException $e) {
                    Notification::make()
                        ->title('No se pudo refinanciar el crédito')
                        ->danger()
                        ->body($e->getMessage())
                        ->persistent()
                        ->send();
                } catch (\Throwable $e) {
                    Notification::make()
                        ->title('Error inesperado')
                        ->danger()
                        ->body('Ocurrió un error al procesar la operación. Contacte al administrador.')
                        ->persistent()
                        ->send();

                    report($e);
                }
            });
    }
}
