<?php

declare(strict_types=1);

namespace App\Filament\Resources\Credits\Actions;

use App\DTOs\ExtendCreditData;
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 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 EXTENDER un crédito.
 *
 * Extensión: Amplía el plazo de pago sin entregar dinero nuevo.
 * El saldo pendiente se redistribuye en más cuotas.
 *
 * IMPORTANTE: La fecha de inicio del nuevo crédito debe ser la fecha
 * de vencimiento del crédito original (puede ser pasada si está vencido).
 */
class ExtendCreditAction
{
    public static function make(): Action
    {
        return Action::make('extend_credit')
            ->label('Extender')
            ->icon('heroicon-o-arrow-path')
            ->color('info')
            ->modalHeading('Extender Crédito')
            ->modalDescription(fn (Credit $record): string => sprintf(
                'Crea un nuevo crédito con el saldo pendiente (%s) redistribuido en más cuotas. NO hay desembolso adicional.',
                '$ '.number_format(app(CreditManager::class)->getRemainingBalance($record), 2, ',', '.')
            )
            )
            ->modalSubmitActionLabel('Extender Crédito')
            ->modalWidth('lg')
            ->visible(fn (?Credit $record): bool => filled($record) && app(CreditOperationOrchestrator::class)->canExtend($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_due_date')
                            ->label('Fecha de vencimiento')
                            ->content(fn () => $record->due_date?->format('d/m/Y') ?? 'No definida'),
                        Placeholder::make('current_periodicity')
                            ->label('Periodicidad actual')
                            ->content(fn () => Periodicity::from($record->periodicity)->getLabel()),
                    ])
                    ->columns(3),

                Section::make('Configuración del nuevo crédito')
                    ->description('La extensión redistribuye el saldo pendiente en nuevas cuotas desde la fecha de vencimiento original.')
                    ->schema([
                        TextInput::make('new_installments')
                            ->label('Número de nuevas cuotas')
                            ->numeric()
                            ->minValue(1)
                            ->maxValue(365)
                            ->default($record->installments_count)
                            ->required()
                            ->helperText('Cantidad de cuotas para el nuevo crédito'),

                        Select::make('periodicity')
                            ->label('Periodicidad')
                            ->options(Periodicity::class)
                            ->default($record->periodicity)
                            ->helperText('Mantener la periodicidad original o cambiar'),

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

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

                Textarea::make('reason')
                    ->label('Motivo de la extensión')
                    ->placeholder('Ej: Cliente solicitó más plazo por dificultades temporales...')
                    ->rows(2)
                    ->columnSpanFull(),
            ])
            ->action(function (array $data, Credit $record) {
                try {
                    $dto = new ExtendCreditData(
                        creditId: $record->id,
                        newInstallmentsCount: (int) $data['new_installments'],
                        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)->extend($dto);

                    Notification::make()
                        ->title('Crédito extendido 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 extender 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 extensión.
     *
     * Regla de negocio:
     * - Si el crédito tiene fecha de vencimiento, usar esa fecha
     * - Si no tiene, usar la fecha de hoy
     */
    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';
    }
}
