<?php

namespace App\Filament\Resources\Payments\Pages;

use App\Filament\Resources\Credits\CreditResource;
use App\Filament\Resources\Payments\PaymentResource;
use App\Models\Credit;
use App\Services\PaymentManager;
use App\Services\Payments\PaymentPolicyException;
use App\Services\Payments\PaymentPolicyValidator;
use Carbon\Carbon;
use Filament\Notifications\Notification;
use Filament\Resources\Pages\CreateRecord;
use Filament\Support\Exceptions\Halt;
use Illuminate\Database\Eloquent\Model;

class CreatePayment extends CreateRecord
{
    protected static string $resource = PaymentResource::class;

    public ?int $creditId = null;

    public function mount(): void
    {
        $this->creditId = request()->integer('credit_id');
        parent::mount(); // necesario para que Filament inicialice el formulario
    }

    protected function mutateFormDataBeforeCreate(array $data): array
    {
        if ($this->creditId) {
            $data['credit_id'] = $this->creditId;
        }
        // $data['company_id'] = auth()->user()->company_id;

        return $data;
    }

    protected function handleRecordCreation(array $data): Model
    {
        $user = auth()->user();

        $paymentDate = Carbon::parse($data['payment_date']);
        $amount = (float) $data['amount'];

        $paymentMethod = $data['payment_method'] ?? 'transfer';
        if ($paymentMethod === 'other' && $data['payment_method_other']) {
            $paymentMethod = $data['payment_method_other'];
        }

        // Solo créditos hoja en estado activo son operacionales (ver CLAUDE.md):
        // antes se usaba findOrFail sin filtro, permitiendo pagar un crédito padre
        // o en estado terminal desde el panel.
        $credit = Credit::query()->activeLeafCredits()->find($data['credit_id']);

        if (! $credit) {
            Notification::make()
                ->title('Crédito no disponible para registrar pagos')
                ->body('El crédito debe estar activo y no ser un crédito padre.')
                ->danger()
                ->send();

            throw new Halt;
        }

        // Mismas políticas de negocio que la PWA (saldo, cuota pendiente,
        // pagos parciales/sobrepagos) vía la fuente única PaymentPolicyValidator.
        try {
            app(PaymentPolicyValidator::class)->validate($credit, $amount);
        } catch (PaymentPolicyException $e) {
            Notification::make()
                ->title('No se pudo registrar el pago')
                ->body($e->getMessage())
                ->danger()
                ->send();

            throw new Halt;
        }

        return app(PaymentManager::class)->registerPayment(
            amount: $amount,
            paymentDate: $paymentDate,
            registeredByUserId: $user->id,
            credit: $credit,
            installment: null,
            paymentMethod: $paymentMethod,
        );
    }

    protected function getRedirectUrl(): string
    {
        // Volver a la página anterior (Credits con filtros/búsqueda),
        // y si por alguna razón no existe, caer al listado de créditos.
        return $this->previousUrl ?? CreditResource::getUrl('index');
    }
}
