<?php

namespace App\Filament\Resources\Credits\Pages;

use App\Enums\CreditAuditEvent;
use App\Filament\Resources\Credits\CreditResource;
use App\Models\Credit;
use App\Services\CreditCalculator;
use App\Services\CreditCascadeDeletionService;
use App\Services\CreditOperationService;
use App\Services\FinanceAutoLogger;
use App\Support\CreditRules;
use Filament\Actions\Action;
use Filament\Actions\ActionGroup;
use Filament\Actions\DeleteAction;
use Filament\Forms\Components\Textarea;
use Filament\Forms\Components\TextInput;
use Filament\Notifications\Notification;
use Filament\Resources\Pages\EditRecord;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Log;

class EditCredit extends EditRecord
{
    protected static string $resource = CreditResource::class;

    /*=========================================================
    | HEADER ACTIONS
    =========================================================*/
    protected function getHeaderActions(): array
    {
        // PATCH — refrescar estado real del crédito
        $this->record->refreshStatus();
        $this->record->refresh();

        return [
            ActionGroup::make([

                // DUPLICAR
                Action::make('duplicate')
                    ->label('Duplicar')
                    ->icon('heroicon-m-document-duplicate')
                    ->color('info')
                    ->visible(fn () => ! $this->record->isClosed() && ! $this->record->hasCapitalPayments())
                    ->requiresConfirmation()
                    ->action(fn () => $this->duplicateCredit()),

                // EXTENDER
                Action::make('extend')
                    ->label('Extender')
                    ->icon('heroicon-m-arrow-path-rounded-square')
                    ->color('warning')
                    ->visible(fn () => ! $this->record->isClosed()
                        && ! CreditRules::hasCapitalPayments($this->record)
                    )
                    ->schema([
                        TextInput::make('new_installments')
                            ->label('Nuevas cuotas')
                            ->numeric()
                            ->required()
                            ->minValue(1),
                    ])
                    ->requiresConfirmation()
                    ->action(fn (array $data) => $this->extendCredit($data['new_installments'])),

                // CANCELAR
                Action::make('cancel')
                    ->label('Cancelar crédito')
                    ->icon('heroicon-m-x-circle')
                    ->color('danger')
                    ->visible(fn () => ! $this->record->isClosed() && ! $this->record->hasCapitalPayments())
                    ->schema([
                        Textarea::make('reason')
                            ->label('Motivo de cancelación')
                            ->rows(4)
                            ->required(),
                    ])
                    ->requiresConfirmation()
                    ->action(fn (array $data) => $this->cancelCredit($data['reason'])),

                DeleteAction::make()
                    ->visible(fn () => ! $this->record->hasCapitalPayments())
                    ->modalDescription(function (): string {
                        /** @var Credit $credit */
                        $credit = $this->record;

                        return 'Al eliminar se devolverán $'.number_format((float) $credit->amount, 0, ',', '.').' a la caja (el desembolso registrado). Úsalo solo si el dinero NUNCA salió (error de registro). Si el cliente recibió el dinero, cancela el crédito en su lugar (mantiene el registro y no mueve la caja).';
                    })
                    ->schema([
                        Textarea::make('reason')
                            ->label('Motivo de la eliminación')
                            ->helperText('Obligatorio. Queda en el log de auditoría. Recuerda: eliminar devuelve el desembolso a la caja.')
                            ->required()
                            ->rows(3),
                    ])
                    // Baja en cascada (limpia todo el rastro financiero), no el delete
                    // por defecto de Filament que dejaría un Expense de desembolso huérfano.
                    ->using(function (Credit $record, array $data): void {
                        Log::warning('Crédito eliminado (hard delete)', [
                            'credit_id' => $record->id,
                            'amount' => (float) $record->amount,
                            'user_id' => auth()->id(),
                            'reason' => $data['reason'] ?? null,
                        ]);

                        app(CreditCascadeDeletionService::class)->deleteCreditCompletely($record);
                    }),

            ])
                ->label('Opciones')
                ->icon('heroicon-m-cog-6-tooth')
                ->color('gray')
                ->button(),
        ];
    }

    /*=========================================================
    | DUPLICAR CRÉDITO
    =========================================================*/
    protected function duplicateCredit()
    {
        $original = $this->record;

        try {
            $new = app(CreditOperationService::class)->executeOperation(
                $original,
                [
                    'operation_type' => 'clone',
                    'new_installments' => $original->installments_count,
                    'amount' => $original->amount,
                ]
            );
        } catch (\Throwable $e) {
            // Incluye PlanLimitExceededException cuando el clon superaría el cupo del plan.
            Notification::make()
                ->title('No se pudo duplicar el crédito')
                ->danger()
                ->body($e->getMessage())
                ->send();

            return;
        }

        Notification::make()
            ->title("Crédito duplicado (#{$new->code})")
            ->success()
            ->send();

        return redirect()->to(
            CreditResource::getUrl('edit', ['record' => $new])
        );
    }

    /*=========================================================
    | EXTENDER CRÉDITO
    =========================================================*/
    protected function extendCredit(int $newInstallments)
    {
        $credit = $this->record;

        $new = app(CreditOperationService::class)->executeOperation(
            $credit,
            [
                'operation_type' => 'extension',
                'new_installments' => $newInstallments,
            ]
        );

        Notification::make()
            ->title("Crédito extendido (#{$new->code})")
            ->success()
            ->send();

        return redirect()->to(
            CreditResource::getUrl('edit', ['record' => $new])
        );
    }

    /*=========================================================
    | CANCELAR CRÉDITO
    =========================================================*/
    protected function cancelCredit(string $reason)
    {
        $credit = $this->record;

        app(CreditOperationService::class)->cancelCredit($credit, $reason);

        Notification::make()
            ->title('Crédito cancelado correctamente')
            ->success()
            ->send();

        return redirect()->to(
            CreditResource::getUrl('index')
        );
    }

    /*=========================================================
    | ACTUALIZAR CRÉDITO — PRO MODE
    | Solo bloquear si hay capital pagado.
    =========================================================*/
    protected function handleRecordUpdate(Model $record, array $data): Model
    {
        /** @var Credit $credit */
        $credit = $record;

        // Política A PRO REVISADA
        if ($credit->hasCapitalPayments()) {
            Notification::make()
                ->title('Este crédito tiene pago de capital')
                ->danger()
                ->body('No puede ser editado según POLÍTICA A PRO.')
                ->send();

            $this->halt();

            return $credit;
        }

        $calculator = app(CreditCalculator::class);
        $finance = app(FinanceAutoLogger::class);

        $original = $credit->replicate()->toArray();

        // Actualiza datos base
        $updated = parent::handleRecordUpdate($credit, $data);

        // Regenerar cuotas (solo si no hay capital pago)
        try {
            $calculator->regenerateInstallments($updated);
        } catch (\Throwable $e) {
            Notification::make()
                ->title('Error al recalcular cuotas')
                ->danger()
                ->body($e->getMessage())
                ->send();
        }

        // Actualizar egreso
        $finance->updateCreditExpense(
            $updated->id,
            $updated->company_id,
            [
                'amount' => $updated->amount,
                'operation_date' => $updated->start_date,
                'collector_user_id' => $updated->collector_user_id,
                'notes' => 'Egreso actualizado tras edición del crédito',
                'metadata' => [
                    'edited_by' => auth()->id(),
                    'old_amount' => $original['amount'],
                    'old_date' => $original['start_date'],
                ],
            ]
        );

        // Auditoría
        app(CreditOperationService::class)->audit(
            creditId: $credit->id,
            action: CreditAuditEvent::CREDIT_EDITED,
            data: [
                'old' => $original,
                'new' => $updated->toArray(),
                'edited_by' => auth()->id(),
            ]
        );

        return $updated;
    }
}
