<?php

declare(strict_types=1);

namespace App\Filament\Resources\Credits\Actions;

use App\DTOs\RestructureCreditData;
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 REESTRUCTURAR un crédito.
 *
 * Reestructuración: Modifica condiciones del crédito SIN dinero nuevo.
 * Puede capitalizar intereses vencidos, cambiar tasa o periodicidad.
 *
 * IMPORTANTE: Similar a extensión, puede iniciar desde la fecha de vencimiento
 * del crédito original (especialmente para créditos en mora).
 */
class RestructureCreditAction
{
    public static function make(): Action
    {
        return Action::make('restructure_credit')
            ->label('Reestructurar')
            ->icon('heroicon-o-wrench-screwdriver')
            ->color('gray')
            ->modalHeading('Reestructurar Crédito')
            ->modalDescription(fn (Credit $record): string => sprintf(
                'Modifica las condiciones del crédito (saldo: %s) sin entregar dinero nuevo. Puede capitalizar intereses vencidos.',
                '$ '.number_format(app(CreditManager::class)->getRemainingBalance($record), 2, ',', '.')
            )
            )
            ->modalSubmitActionLabel('Reestructurar Crédito')
            ->modalWidth('lg')
            ->visible(fn (?Credit $record): bool => filled($record) && app(CreditOperationOrchestrator::class)->canRestructure($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_status')
                            ->label('Estado actual')
                            ->content(fn () => $record->getStatusLabel()),
                    ])
                    ->columns(3),

                Section::make('Capitalización de Intereses (Opcional)')
                    ->description('Puede agregar intereses vencidos al capital si es necesario.')
                    ->schema([
                        TextInput::make('capitalized_interest')
                            ->label('Intereses a capitalizar')
                            ->numeric()
                            ->minValue(0)
                            ->default(0)
                            ->prefix('$')
                            ->live(onBlur: true)
                            ->helperText('Intereses vencidos que se agregarán al capital'),

                        Placeholder::make('new_principal')
                            ->label('Nuevo capital resultante')
                            ->content(function ($get) use ($record) {
                                $balance = app(CreditManager::class)->getRemainingBalance($record);
                                $capitalized = (float) ($get('capitalized_interest') ?? 0);
                                $total = $balance + $capitalized;

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

                Section::make('Nuevas condiciones del 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('Puede reducir la tasa como parte de la negociación'),

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

                        DatePicker::make('start_date')
                            ->label('Fecha de inicio del nuevo crédito')
                            ->default(fn () => self::getDefaultStartDate($record))
                            ->helperText(fn () => self::getStartDateHelperText($record))
                            ->required(),

                        DatePicker::make('first_due_date_override')
                            ->label('Primera fecha de vencimiento (opcional)')
                            ->helperText('Puede dar período de gracia'),
                    ])
                    ->columns(2),

                Textarea::make('reason')
                    ->label('Motivo de la reestructuración')
                    ->placeholder('Ej: Negociación por dificultades de pago. Se reduce tasa y se extiende plazo...')
                    ->rows(2)
                    ->required()
                    ->columnSpanFull(),
            ])
            ->action(function (array $data, Credit $record) {
                try {
                    $dto = new RestructureCreditData(
                        creditId: $record->id,
                        newInstallmentsCount: (int) $data['new_installments'],
                        capitalizedInterest: Money::of((float) ($data['capitalized_interest'] ?? 0)),
                        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)->restructure($dto);

                    Notification::make()
                        ->title('Crédito reestructurado 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 reestructurar 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);
                }
            });
    }

    /**
     * Determina la fecha de inicio por defecto para la reestructuración.
     */
    private static function getDefaultStartDate(Credit $record): Carbon
    {
        if ($record->due_date) {
            return Carbon::parse($record->due_date);
        }

        return Carbon::today();
    }

    /**
     * Genera el texto de ayuda contextual para la fecha de inicio.
     */
    private static function getStartDateHelperText(Credit $record): string
    {
        if ($record->due_date) {
            $dueDate = Carbon::parse($record->due_date);
            $isOverdue = $dueDate->isPast();

            if ($isOverdue) {
                return sprintf(
                    'Crédito vencido el %s. Se recomienda iniciar desde esa fecha.',
                    $dueDate->format('d/m/Y')
                );
            }

            return sprintf('Fecha de vencimiento: %s', $dueDate->format('d/m/Y'));
        }

        return 'Fecha desde la cual inicia el nuevo crédito';
    }
}
